Facebook Graph API - upload photo using JavaScript

前端 未结 13 1325
温柔的废话
温柔的废话 2020-11-27 11:03

Is it possible to upload a file using the Facebook Graph API using javascript, I feel like I\'m close. I\'m using the following JavaScript

var params = {};
         


        
13条回答
  •  爱一瞬间的悲伤
    2020-11-27 11:47

    Only @Thiago's answer is answering the question of uploading data via javascript. I've found that the Facebook JS API doesn't cover this situation.

    I've also brew & tested my personl solution.

    Main steps

    1. Get the binary data of the image (I've used a canvas, but using an input box is possible as well)
    2. Form a multipart request with all necesarry data for the graph API call
    3. Include the binary data in the request
    4. Encode everything in a binary array and send it so via XHR

    Code

    Conversion utilities

    var conversions = {
      stringToBinaryArray: function(string) {
        return Array.prototype.map.call(string, function(c) {
          return c.charCodeAt(0) & 0xff;
        });
      },
      base64ToString: function(b64String) {
        return atob(b64String);
      }
    };
    

    Image posting snippet

    var DEFAULT_CALL_OPTS = {
      url: 'https://graph.facebook.com/me/photos',
      type: 'POST',
      cache: false,
      success: function(response) {
        console.log(response);
      },
      error: function() {
        console.error(arguments);
      },
      // we compose the data manually, thus
      processData: false,
      /**
       *  Override the default send method to send the data in binary form
       */
      xhr: function() {
        var xhr = $.ajaxSettings.xhr();
        xhr.send = function(string) {
          var bytes = conversions.stringToBinaryArray(string);
          XMLHttpRequest.prototype.send.call(this, new Uint8Array(bytes).buffer);
        };
        return xhr;
      }
    };
    /**
     * It composes the multipart POST data, according to HTTP standards
     */
    var composeMultipartData = function(fields, boundary) {
      var data = '';
      $.each(fields, function(key, value) {
        data += '--' + boundary + '\r\n';
    
        if (value.dataString) { // file upload
          data += 'Content-Disposition: form-data; name=\'' + key + '\'; ' +
            'filename=\'' + value.name + '\'\r\n';
          data += 'Content-Type: ' + value.type + '\r\n\r\n';
          data += value.dataString + '\r\n';
        } else {
          data += 'Content-Disposition: form-data; name=\'' + key + '\';' +
            '\r\n\r\n';
          data += value + '\r\n';
        }
      });
      data += '--' + boundary + '--';
      return data;
    };
    
    /**
     * It sets the multipart form data & contentType
     */
    var setupData = function(callObj, opts) {
      // custom separator for the data
      var boundary = 'Awesome field separator ' + Math.random();
    
      // set the data
      callObj.data = composeMultipartData(opts.fb, boundary);
    
      // .. and content type
      callObj.contentType = 'multipart/form-data; boundary=' + boundary;
    };
    
    // the "public" method to be used
    var postImage = function(opts) {
    
      // create the callObject by combining the defaults with the received ones
      var callObj = $.extend({}, DEFAULT_CALL_OPTS, opts.call);
    
      // append the access token to the url
      callObj.url += '?access_token=' + opts.fb.accessToken;
    
      // set the data to be sent in the post (callObj.data = *Magic*)
      setupData(callObj, opts);
    
      // POST the whole thing to the defined FB url
      $.ajax(callObj);
    };
    

    Usage

    postImage({
      fb: { // data to be sent to FB
        caption: caption,
        /* place any other API params you wish to send. Ex: place / tags etc.*/
        accessToken: 'ACCESS_TOKEN',
        file: {
          name: 'your-file-name.jpg',
          type: 'image/jpeg', // or png
          dataString: image // the string containing the binary data
        }
      },
      call: { // options of the $.ajax call
        url: 'https://graph.facebook.com/me/photos', // or replace *me* with albumid
        success: successCallbackFunction,
        error: errorCallbackFunction
      }
    });
    

    Extra

    Extracting the binary string representation of a canvas image

    var getImageToBeSentToFacebook = function() {
      // get the reference to the canvas
      var canvas = $('.some-canvas')[0];
    
      // extract its contents as a jpeg image
      var data = canvas.toDataURL('image/jpeg');
    
      // strip the base64 "header"
      data = data.replace(/^data:image\/(png|jpe?g);base64,/, '');
    
      // convert the base64 string to string containing the binary data
      return conversions.base64ToString(data);
    }
    

    Information on how to load the binaryString from an input[type=file]

    HTML5 File API read as text and binary

    Notes:

    1. There are of course alternative approaches as well
      • Using an HTML form in an iframe - you cannot get the response from the call
      • Using a FormData & File approach, but unfortunately in this case there are a lot of incompatilities which make the process harder to use, and you would end up duct-taping around the inconsistencies - thus my choice was manual data assembly since HTTP standards rarely change :)
    2. The solution does not require any special HTML5 features.
    3. The above example uses jQuery.ajax, jQuery.extend, jQuery.each

提交回复
热议问题