Skip to content

Instantly share code, notes, and snippets.

@andyburke
Created December 19, 2011 20:37
Show Gist options
  • Star 42 You must be signed in to star a gist
  • Fork 10 You must be signed in to fork a gist
  • Save andyburke/1498758 to your computer and use it in GitHub Desktop.
Save andyburke/1498758 to your computer and use it in GitHub Desktop.
How to post a photo to Facebook from client-side Javascript
// 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 );
}
@coire1
Copy link

coire1 commented Sep 15, 2012

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

@jsalden
Copy link

jsalden commented Dec 13, 2012

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!

@nunziofiore
Copy link

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

@pablolemosassis
Copy link

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!!

Copy link

ghost commented Apr 11, 2013

thanks.

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

@coire1
Copy link

coire1 commented Apr 12, 2013

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!

Copy link

ghost commented Apr 13, 2013

lol

@masad-mz
Copy link

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

@euharrison
Copy link

thanks, you saved me :)

    var img = document.createElement('img');
    img.src = 'http://localhost/quadrinhos/shareImage.png';
    img.onload = function () {
        var canvas = document.createElement("canvas"); 
        canvas.width = img.width; 
        canvas.height = img.height; 
        var ctx = canvas.getContext("2d"); 
        ctx.drawImage(img,0,0);
        var c = canvas.toDataURL('image/png');
        var encodedPng = c.substring(c.indexOf(',')+1,c.length);
        var decodedPng = Base64Binary.decode(encodedPng);

        PostImageToFacebook(response.authResponse.accessToken, 'shareImage.png', 'image/png', decodedPng, '');
    }

@jarib
Copy link

jarib commented Oct 9, 2015

This doesn't handle non-ASCII in the message part. Anyone know how to solve that?

@mjaensch
Copy link

I solved the charset problem using the following code in line 46:

formData += 'Content-Type: text/plain; charset=UTF-8\r\n';
formData += 'Content-Disposition: form-data; name="message"\r\n\r\n';
formData += unescape(encodeURIComponent(message)) + '\r\n'
formData += '--' + boundary + '--\r\n';

@arunxavy
Copy link

any one found a way to do this on IE9 ?

@ravi24391
Copy link

great snippet, it seems good for other browser but it fail on safari... can you help me?
getting this error:

------ThisIsTheBoundary1234567890--

photosPOST https://graph.facebook.com/me/photos?access_token=xyzzzzz 400 (Bad Request)
configurator:1440{
"error": {
"message": "(#324) Requires upload file",
"type": "OAuthException",
"code": 324,
"fbtrace_id": "C6NDlXMUwAy"
}
}

@AbdulKadir-Agoliya
Copy link

i Got this error

{
"error": {
"message": "(#200) Requires extended permission: publish_actions",
"type": "OAuthException",
"code": 200,
"fbtrace_id": "CnTkONRU26Z"
}
}

But i dont getting how to get permission publish_actions

i tried to give permission using my App but

publish_actions_fb

Is anyone have solved publish_actions permission issue?

@shukerullah
Copy link

@AbdulKadir-Ago, how did you fix this publish_actions issue?

@tauseedzaman
Copy link

i have the same issue with how to upload images from a computer
code: 324
fbtrace_id: "A4xR8fZio4tZUhEF2IInbWM"
message: "(#324) Requires upload file"
type: "OAuthException"

@tauseedzaman
Copy link

i Got this error

{ "error": { "message": "(#200) Requires extended permission: publish_actions", "type": "OAuthException", "code": 200, "fbtrace_id": "CnTkONRU26Z" } }

But i dont getting how to get permission publish_actions

i tried to give permission using my App but

publish_actions_fb

Is anyone have solved publish_actions permission issue?

goto your facebook developer graph api explorer you will find options for settings all permissions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment