public
Last active

How to post a photo to Facebook from client-side Javascript

  • Download Gist
facebook-photo-post-javascript.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
// This bit is important. It detects/adds XMLHttpRequest.sendAsBinary. Without this
// you cannot send image data as part of a multipart/form-data encoded request from
// Javascript. This implementation depends on Uint8Array, so if the browser doesn't
// support either XMLHttpRequest.sendAsBinary or Uint8Array, then you will need to
// find yet another way to implement this. (This is left as an exercise for the reader,
// but if you do it, please let me know and I'll integrate it.)
 
// from: http://stackoverflow.com/a/5303242/945521
 
if ( XMLHttpRequest.prototype.sendAsBinary === undefined ) {
XMLHttpRequest.prototype.sendAsBinary = function(string) {
var bytes = Array.prototype.map.call(string, function(c) {
return c.charCodeAt(0) & 0xff;
});
this.send(new Uint8Array(bytes).buffer);
};
}
 
// This function takes an array of bytes that are the actual contents of the image file.
// In other words, if you were to look at the contents of imageData as characters, they'd
// look like the contents of a PNG or GIF or what have you. For instance, you might use
// pnglib.js to generate a PNG and then upload it to Facebook, all from the client.
//
// Arguments:
// authToken - the user's auth token, usually from something like authResponse.accessToken
// filename - the filename you'd like the uploaded file to have
// mimeType - the mime type of the file, eg: image/png
// imageData - an array of bytes containing the image file contents
// message - an optional message you'd like associated with the image
 
function PostImageToFacebook( authToken, filename, mimeType, imageData, message )
{
// this is the multipart/form-data boundary we'll use
var boundary = '----ThisIsTheBoundary1234567890';
// let's encode our image file, which is contained in the var
var formData = '--' + boundary + '\r\n'
formData += 'Content-Disposition: form-data; name="source"; filename="' + filename + '"\r\n';
formData += 'Content-Type: ' + mimeType + '\r\n\r\n';
for ( var i = 0; i < imageData.length; ++i )
{
formData += String.fromCharCode( imageData[ i ] & 0xff );
}
formData += '\r\n';
formData += '--' + boundary + '\r\n';
formData += 'Content-Disposition: form-data; name="message"\r\n\r\n';
formData += message + '\r\n'
formData += '--' + boundary + '--\r\n';
var xhr = new XMLHttpRequest();
xhr.open( 'POST', 'https://graph.facebook.com/me/photos?access_token=' + authToken, true );
xhr.onload = xhr.onerror = function() {
console.log( xhr.responseText );
};
xhr.setRequestHeader( "Content-Type", "multipart/form-data; boundary=" + boundary );
xhr.sendAsBinary( formData );
}

I modified this code in:

xhr.open( 'POST', 'https://graph.facebook.com/'+albumId+'/photos?access_token=' + authToken, true );

//post to graph album

But the function return this error:

400 (Bad Request)
fb-album.js:120{
   "error": {
      "message": "(#1) An unknown error occurred",
      "type": "OAuthException",
      "code": 1
   }
}

Do you have any idea to fix this problems?
Thanks

I would check to make sure the authToken you're using gives permission to post to the given album.

Hi, i'm trying to use your code getting the image source from a HTML5 canvas element:
after generating image with canvas i convert it with

  source = img.toDataURL('image/png'); 

and upload it on Fb calling your function:

  PostImageToFacebook( accessToken, 'img.png', 'image/png', source, 'js upload' );

but the function return this error:

  400 (Bad Request)
  fbapp.js:439{
   "error": {
      "message": "(#1) An unknown error occurred",
      "type": "OAuthException",
      "code": 1
   }
  }

I'm sure that my authToken have the right permissions (i can do it in php!)
How can I fix it?
Thank you

Thanks Andy, this was very helpful!

coire1, I had the same "unknown error." In case you still need a solution, or for others who come across this, here's what worked for me:

You need to base64 decode the canvas output which can be done using this: https://github.com/danguer/blog-examples/blob/master/js/base64-binary.js

So my code ended up something like this:

var c = canvas.toDataURL('image/png');
var encodedPng = c.substring(c.indexOf(',')+1,c.length);
var decodedPng = Base64Binary.decode(encodedPng);

After that, I feed decodedPng into Andy's function, and it works great!

this is a great snippet, it seems ok on chrome but it fail on safari... can you help me?

I can confirm that it works on all decent browsers (i.e. all but IE), including Safari Mobile at iOS 5.1.
IE 9 (didn test 10) is the only one not supportting Uint8Array.

It is mandatory to use jsalden encoding/decoding approach.

Thanks a lot andyburke and jsalden. Doing this was the most hermetic stuff I've ever done in my developer career!!

thanks.

and some keywords for google: canvas upload photo facebook javascript javascriptsdk

I had give up hope. After 4 months i googled the same keywords, found this thread with my comment and....A SOLUTION!!! Wonderful! Thanks andyburke and jsalden!

I am getting this. Can anybody help me out
[00:15:45.797] "{
"error": {
"message": "(#1) An unknown error occurred",
"type": "OAuthException",
"code": 1
}
}"

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.