Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Uploading a canvas image to facebook as Blob of multipart/form-data type

I am trying to use the facebook api to upload an image from a canvas I save on the page:

var file = dataURItoBlob(canvas.toDataURL('image/jpeg', 1.0))

FB.api('/me/photos', 'POST', {
  source: file,
  message: 'photo description'
}, function (response) {
    console.log(response)
  }
)

This is the blob convertor:

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/jpeg' });
}

And I am getting an error: message: "(#324) Requires upload file" so it seems the uploader does not recognize the blob as a valid file.


UPDATE 1:

I fount this post: Convert Data URI to File then append to FormData about converting blob to formData, tried it like this:

var dataURL = canvas.toDataURL('image/jpeg', 1.0)
var blob = dataURItoBlob(dataURL)
var fd = new FormData(document.forms[0])
fd.append("canvasImage", blob)

FB.api('/me/photos', 'POST', {
  source: fd .....

But still the same error.


UPDATE 2:

Even tried this XHR post solution, Using Facebooks javascript api to post multipart/form-data encoded image and still getting file issue "Your photos couldn't be uploaded. Photos should be less than 4 MB and saved as JPG, PNG, GIF or TIFF files."

function postImageToFacebook(access_token) {
  var filename = "samplepic.png",
    mimeType = "image/png",
    message = "test comment",
    data = canvas.toDataURL("image/png"),
    encodedPng = data.substring(data.indexOf(',') + 1, data.length),
    imageData = atob(encodedPng);

  // build the multipart/form-data
  var boundary = '----ThisIsTheBoundary1234567890';
  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/v2.5/me/photos?access_token=' + access_token, true );
  xhr.onload = xhr.onerror = function() {
    console.log( xhr.responseText );
  };
  xhr.setRequestHeader( "Content-Type", "multipart/form-data; boundary=" + boundary );
  xhr.send( formData );
}
like image 608
ilyo Avatar asked Mar 07 '16 13:03

ilyo


2 Answers

I figured out, for some reason, the issues was the headers that I tried to apply as a solution for a previous problem... Here is a working solution: https://jsfiddle.net/ilyador/vyne7oh2/8/

function fbUpload(token){
  var dataURL = canvas.toDataURL('image/jpeg', 1.0)
  var blob = dataURItoBlob(dataURL)
  var formData = new FormData()
  formData.append('token', token)
  formData.append('source', blob)

  var xhr = new XMLHttpRequest();
  xhr.open( 'POST', 'https://graph.facebook.com/me/photos', true )
  xhr.onload = xhr.onerror = function() {
    console.log( xhr.responseText )
  };
  xhr.send( formData )
}

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/jpeg' });
}
like image 61
ilyo Avatar answered Nov 11 '22 09:11

ilyo


To upload directly from canvas to Facebook photos, this works for me:

function postImageToFacebook(token, imageData, message, successCallback, errorCallback) {
  var fd = new FormData();
  fd.append("access_token", token);
  fd.append("source", imageData);
  fd.append("caption", message);

  $.ajax({
      url: "https://graph.facebook.com/me/photos?access_token=" + token,
      type: "POST",
      data: fd,
      processData: false,
      contentType: false,
      cache: false,
      success: function (data) {
        successCallback(data);
      },
      error: function (shr, status, data) {
        errorCallback(data);
      },
      complete: function (data) {
        console.log('Completed');
      }
  });
}

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/jpeg'});
}

To use it

// *IMPORTANT*
var FBLoginScope = 'publish_actions'; // or sth like 'user_photos,publish_actions' if you also use other scopes.

var caption = "Hello Facebook!";
var successCallback = ...;
var errorCallback = ...;

var data = $('#your_canvas_id')[0].toDataURL("image/jpeg");
try {
  imageData = dataURItoBlob(data);
} catch (e) {
  console.log(e);
}

FB.getLoginStatus(function (response) {
  if (response.status === "connected") {
    postImageToFacebook(response.authResponse.accessToken, imageData, caption, successCallback, errorCallback);
  } else if (response.status === "not_authorized") {
    FB.login(function (response) {
        postImageToFacebook(response.authResponse.accessToken, imageData, caption, successCallback, errorCallback);
    }, {scope: FBLoginScope});
  } else {
    FB.login(function (response) {
        postImageToFacebook(response.authResponse.accessToken, imageData, caption, successCallback, errorCallback);
    }, {scope: FBLoginScope});
  }
});

Modified from: http://gorigins.com/posting-a-canvas-image-to-facebook-and-twitter/

like image 28
aunnnn Avatar answered Nov 11 '22 08:11

aunnnn