Upload Base64 Image Facebook Graph API

25,375

Solution 1

The code above didn't quite work for me (Missing comma after type:"POST", and data URI to blob function reported errors. I got the following code to work in Firefox and Chrome:

function PostImageToFacebook(authToken)
{
    var canvas = document.getElementById("c");
    var imageData  = canvas.toDataURL("image/png");
    try {
        blob = dataURItoBlob(imageData);
    }
    catch(e) {
        console.log(e);
    }
    var fd = new FormData();
    fd.append("access_token",authToken);
    fd.append("source", blob);
    fd.append("message","Photo Text");
    try {
        $.ajax({
            url:"https://graph.facebook.com/me/photos?access_token=" + authToken,
            type:"POST",
            data:fd,
            processData:false,
            contentType:false,
            cache:false,
            success:function(data){
                console.log("success " + data);
            },
            error:function(shr,status,data){
                console.log("error " + data + " Status " + shr.status);
            },
            complete:function(){
                console.log("Posted to facebook");
            }
        });
    }
    catch(e) {
        console.log(e);
    }
}

function dataURItoBlob(dataURI) {
    var byteString = atob(dataURI.split(',')[1]);
    var ab = new ArrayBuffer(byteString.length);
    var ia = new Uint8Array(ab);
    for (var i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
    }
    return new Blob([ab], { type: 'image/png' });
}

Here's the code at GitHub https://github.com/DanBrown180/html5-canvas-post-to-facebook-base64

Solution 2

I hope this will be useful. By doing photo upload to FB only with the help of javascript you can use the following method. Required thing here are imageData(which is base64 format of image) and the mime type.

try {
    blob = dataURItoBlob(imageData,mimeType);
} catch (e) {
    console.log(e);
}

var fd = new FormData();
fd.append("access_token",accessToken);
fd.append("source", blob);
fd.append("message","Kiss");

try {
   $.ajax({
        url:"https://graph.facebook.com/" + <<userID received on getting user details>> + "/photos?access_token=" + <<user accessToken>>,
        type:"POST",
        data:fd,
        processData:false,
        contentType:false,
        cache:false,
        success:function(data){
            console.log("success " + data);
        },
        error:function(shr,status,data){
            console.log("error " + data + " Status " + shr.status);
        },
        complete:function(){
            console.log("Ajax Complete");
        }
   });

} catch(e) {
    console.log(e);
}

function dataURItoBlob(dataURI,mime) {
    // convert base64 to raw binary data held in a string
    // doesn't handle URLEncoded DataURIs

    var byteString = window.atob(dataURI);

    // separate out the mime component


    // write the bytes of the string to an ArrayBuffer
    //var ab = new ArrayBuffer(byteString.length);
    var ia = new Uint8Array(byteString.length);
    for (var i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
    }

    // write the ArrayBuffer to a blob, and you're done
    var blob = new Blob([ia], { type: mime });

    return blob;
}

//EDIT AJAX SYNTAX

Solution 3

Dan's Answer works the best. Something else that might be helpful in this scenario is the optional argument for posting photos: 'no_story'. This arg defaults to true forcing the photo-post to skip the user's wall. By adding

fd.append("no_story", false);

you can update the user's wall with the photo-post.

I would have just left this as a comment but... 50 Rep for comments.

Solution 4

We can simplify image recoding by usage of the modern Fetch API instead of Uint8Array.

 var url = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="

 fetch(url)
  .then(res => res.blob())
  .then(blob => console.log(blob))`

Solution 5

Here is an example that does not need jQuery or other libraries, just the native Fetch API:

const dataURItoBlob = (dataURI) => {
    let byteString = atob(dataURI.split(',')[1]);
    let ab = new ArrayBuffer(byteString.length);
    let ia = new Uint8Array(ab);
    for (let i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
    }
    return new Blob([ia], {
        type: 'image/jpeg'
    });
}
const upload = async (response) => {
    let canvas = document.getElementById('canvas');
    let dataURL = canvas.toDataURL('image/jpeg', 1.0);
    let blob = dataURItoBlob(dataURL);
    let formData = new FormData();
    formData.append('access_token', response.authResponse.accessToken);
    formData.append('source', blob);

    let responseFB = await fetch(`https://graph.facebook.com/me/photos`, {
        body: formData,
        method: 'post'
    });
    responseFB = await responseFB.json();
    console.log(responseFB);
};
document.getElementById('upload').addEventListener('click', () => {
    FB.login((response) => {
        //TODO check if user is logged in and authorized publish_actions
        upload(response);
    }, {scope: 'publish_actions'})
})

Source: http://www.devils-heaven.com/facebook-javascript-sdk-photo-upload-from-canvas/

Share:
25,375

Related videos on Youtube

Mauro
Author by

Mauro

Updated on April 07, 2020

Comments

  • Mauro
    Mauro about 4 years

    I'm trying to upload a base64 image to a FaceBook page using Node.js. I have managed to get the upload working with all the multipart data etc should I read the file from the filesystem (ie. using fs.readFileSync('c:\a.jpg')

    However, should I use the base64 encoded image and try upload it, it give me the following error : {"error":{"message":"(#1) An unknown error occurred","type":"OAuthException","code":1}}

    I have tried converting it to binary by new Buffer(b64string, 'base64'); and uploading that, but no luck.

    I have been struggling with this for 3 days now, so anyhelp would be greatly appreciated.

    Edit : If anyone also knows how I could convert the base64 to binary and successfully upload it, that would also work for me.

    Edit : Code Snippet

    var postDetails = separator + newlineConstant + 'Content-Disposition: form-data;name="access_token"' + newlineConstant + newlineConstant + accessToken + newlineConstant + separator;
    
    postDetails = postDetails + newlineConstant + 'Content-Disposition: form-data; name="message"' + newlineConstant + newlineConstant + message + newlineConstant;
    
    //Add the Image information
    var fileDetailsString = '';
    var index = 0;
    var multipartBody = new Buffer(0);
    images.forEach(function (currentImage) {
        fileDetailsString = fileDetailsString + separator + newlineConstant + 'Content-Disposition: file; name="source"; filename="Image' + index + '"' + newlineConstant + 'Content-Type: image/jpeg' + newlineConstant + newlineConstant;
        index++;
    
        multipartBody = Buffer.concat([multipartBody, new Buffer(fileDetailsString), currentImage]); //This is what I would use if Bianry data was passed in 
    
        currentImage = new Buffer (currentImage.toString('base64'), 'base64'); // The following lines are what I would use for base64 image being passed in (The appropriate lines would be enabled/disabled if I was using Binary/base64)
        multipartBody = Buffer.concat([multipartBody, new Buffer(fileDetailsString), currentImage]);
    });
    
    multipartBody = Buffer.concat([new Buffer(postDetails), multipartBody, new Buffer(footer)]);
    
    • loganfsmyth
      loganfsmyth about 11 years
      Where is the b64String coming from? Are you sure it's not a data URL? Please show some example data if you console.log(b64string).
    • Brune
      Brune almost 11 years
      Could you provide any sample of uploading base64 through javascript ajax.
    • Mauro
      Mauro almost 11 years
      Hey guys, sorry for the late reply...been away. it definitely isn't a data URL...here is a snippet of the beginning of the data.../9j/4AAQSkZJRgABAQEASABIAAD/2wBDABcQERQRDhcUEhQaGBcbI‌​jk @Brune I have updated the post to put a snippet of the upload section. The multipart data etc all works as when I have a binary image passed it all works 100% but when I have a base64 image passed in it doesn't work.
    • Brune
      Brune almost 11 years
      Does this related to Node.js.. I've base64 image data and struck with the structure of ajax request(what should go in header and body).. I've got Invalid request error..
  • Justin McCraw
    Justin McCraw almost 11 years
    Did you get this to work? I couldn't get a correct response. And for the dataURI, do you remove the "data:image/png;base64," part?
  • Brune
    Brune almost 11 years
    Yeah. It is working fine. Yes, you've to remove the "data:image/png;base64," portion when you send it for blob conversion.
  • Justin McCraw
    Justin McCraw almost 11 years
    Holy, moly. This worked! Should have tweaked it more before complaining here. You're a miracle worker!
  • Lagoo87
    Lagoo87 about 10 years
    I've tried your code out and my communication w Facebook seems to be working, but I have an issue that the fd (FormData) is empty, just showing empty arrays. Any ideas?
  • Lagoo87
    Lagoo87 about 10 years
    Hope someone sees this! Am attempting the same thing, but I seem to always be receiving an error back from Facebook with my FormData showing empty arrays. Any ideas??!
  • Brune
    Brune about 10 years
    What error are you receiving?? Do you mean to say your formdata is not passed to facebook??
  • Pedro Souza
    Pedro Souza about 10 years
    I have tried use FB.api() but without success. And now, I tested this code and works! Hell yeaaah! Thanks :)
  • Boyan Hristov
    Boyan Hristov over 9 years
    I am using this code and always get an error from Facebook saying 'Bad Request'. Any ideas?
  • Brune
    Brune over 9 years
    did you remove the data identification portion of your base64 content "data:image/png:base64"??
  • David Augustus
    David Augustus over 8 years
    Ths one works, i also used this many ways . The hot is the "dataURItoBlob", BLOB, thats the keyword :P
  • Alexis Wilke
    Alexis Wilke over 7 years
    That sounds like an important feature! And hey... you need to spend more time here!
  • Alexis Wilke
    Alexis Wilke over 7 years
    This is great as you show us how to get the actual authorization parameters to contact Facebook.
  • codeinaire
    codeinaire over 4 years
    The only problem with this is that it's an experimental feature (caniuse.com/#feat=mdn-api_body_blob). So be careful when using it in production.