Facebook Graph API - 使用 JavaScript 上传照片

IT技术 javascript facebook facebook-graph-api file-upload
2021-02-18 04:39:02

是否可以使用 javascript 使用 Facebook Graph API 上传文件,我觉得我很接近。我正在使用以下 JavaScript

var params = {};
params['message'] = 'PicRolled';
params['source'] = '@'+path;
params['access_token'] = access_token;
params['upload file'] = true;

function saveImage() {
    FB.api('/me/photos', 'post', params, function(response) {
        if (!response || response.error) {
            alert(response);
        } else {
            alert('Published to stream - you might want to delete it now!');
        }
    }); 
}

运行此程序后,我收到以下错误...

"OAuthException" - "(#324) Requires upload file"

当我尝试研究这种方法时,我只能找到一种可以解决此问题的 php 方法

$facebook->setFileUploadSupport(true);

但是,我使用的是 JavaScript,看起来这种方法可能与 Facebook Graph 权限有关,但我已经设置了权限 user_photos 和 publish_stream,我认为这是执行此操作所需的唯一权限。

我在 stackoverflow 上看到了几个与此相关的悬而未决的问题,希望我能对自己进行足够的解释。多谢你们。

6个回答

是的,这是可能的,我找到了 2 个解决方案,它们彼此非常相似,您只需将 url 参数定义为外部图像 url

第一个使用 Javascript SDK:

var imgURL="http://farm4.staticflickr.com/3332/3451193407_b7f047f4b4_o.jpg";//change with your external photo url
FB.api('/album_id/photos', 'post', {
    message:'photo description',
    url:imgURL        
}, function(response){

    if (!response || response.error) {
        alert('Error occured');
    } else {
        alert('Post ID: ' + response.id);
    }

});

使用第二个jQuery的Post请求和FORMDATA:

 var postMSG="Your message";
 var url='https://graph.facebook.com/albumID/photos?access_token='+accessToken+"&message="+postMSG;
 var imgURL="http://farm4.staticflickr.com/3332/3451193407_b7f047f4b4_o.jpg";//change with your external photo url
 var formData = new FormData();
 formData.append("url",imgURL);

  $.ajax({
                    url: url,
                    data: formData,
                    cache: false,
                    contentType: false,
                    processData: false,
                    type: 'POST',

                    success: function(data){
                        alert("POST SUCCESSFUL");
                    }
                });
当然,您需要添加 jquery 库;)
2021-04-18 04:39:02
第一个工作完美,我不知道为什么文档甚至没有指定 url 参数。
2021-04-18 04:39:02
@Oso 我收到 500 条消息已经有一段时间了,现在似乎没问题。Владимир Дворник,非常感谢您引用 url 参数,api 文档确实很糟糕。
2021-04-26 04:39:02
这种方法停止工作了吗?我一直在使用第一种方法几个月,然后突然失败(发送无效的图像消息)并尝试使用第二种方法并给我相同的错误消息。
2021-05-12 04:39:02
我使用了第二个,它给了我:“$ 未定义”
2021-05-15 04:39:02

编辑:这个答案(现在)在很大程度上无关紧要。如果您的图像在网络上,只需url根据API指定参数(并查看其他答案中的示例)。如果您想直接将图像内容发布到 facebook,您可能需要阅读此答案以获取理解。另请参阅 HTML5 的Canvas.toDataUrl().

API:“要发布照片,请使用照片文件附件作为 multipart/form-data发出 POST 请求。”

FB 期望要上传的图像字节在 HTTP 请求的正文中,但它们不在那里。或者以另一种方式看待它 - 您在 FB.api() 调用中的哪个位置提供图像本身的实际内容?

所述FB.api() API记录不当,并且不提供的HTTP POST,其包括主体的一个例子。人们可能会从没有这样一个例子中推断出它不支持这一点。

这可能没问题 - FB.api() 正在使用一种称为undercovers 的东西XmlHttpRequest,它确实支持包含一个主体......在你最喜欢的 JavaScript 参考中查找它。

但是,您仍然需要解决 2 个子问题:

  1. 如何将图像字节(以及请求的其余部分)准备为multipart/form-data
  2. 获取图像本身的字节

(顺便说一句,对消息体进行编码的需要可能是 PHP setFileUploadSupport(true) 方法的用途——告诉facebook对象multipart/form-data在发送之前对消息体进行编码

但它比那更混乱

不幸的是,子问题“2”可能会困扰您 - 没有办法(我上次查看)从浏览器提供的 Image 对象中提取图像的字节。

如果要上传的图像可通过 URL 访问,则可以使用 XmlHttpRequest 获取字节。还不错。

如果图像来自用户的桌面,您可能的方法是为用户提供:

 <form enctype="multipart/form-data">
     <input type="filename" name="myfile.jpg" />
     <input type="hidden" name="source" value="@myfile.jpg"/>
     <input type="hidden" name="message" value="My Message"/>
     <input type="hidden" name="access_token" value="..."/> 
 </form> 

(注意source引用了文件上传小部件的名称)

...并希望 FB 预期以这种方式接收数据(先尝试使用静态 HTML 表单,然后再在 JS 中对其进行动态编码)。人们可能会推断,事实上它会,因为他们没有提供另一种方法来做到这一点。

Bullock 路径可以从 url 访问,所以你认为它会是一个 xml http 请求来提供图像数据而不是路径,我的其余代码看起来没问题吗?我不能尝试直到今晚晚些时候,但再次感谢
2021-04-22 04:39:02
最终,要使用这个 api,您需要获取图像的字节,然后将包含这些字节的请求编码为 multipart/form-data,然后将其作为 POST 请求的正文发送到 facebook 服务器。
2021-04-25 04:39:02
嗨,大卫,如果字节来自 canvas.toDataURL()(假设我们解码 base64),那么在 HTTP POST 请求的正文中上传是否有效?
2021-05-02 04:39:02
谢谢,也许我应该使用 php,它看起来更直接,但我会先尝试这个!
2021-05-04 04:39:02
如果您有闲暇时间让服务器上传图像,那么无论如何我都可能会这样做。您将不会因为 XmlHttpRequest 对象在各种浏览器中尚未成为标准的二进制功能而感到头疼,而且您不会对同源策略感到头疼。无论如何,服务器很可能比浏览器“连接得更好”,并且可以更快地完成工作。
2021-05-04 04:39:02

我使用了@Владимир Дворник 代码并进行了一些修改,我遇到了同样的问题,并且使用此代码效果很好:

        var imgURL = //your external photo url
        FB.api('/photos', 'post', {
            message: 'photo description',
            access_token: your accesstoken 
            url: imgURL
        }, function (response) {

            if (!response || response.error) {
                alert('Error occured:' + response);
            } else {
                alert('Post ID: ' + response.id);
            }

        });
为什么它会自动创建相册
2021-04-16 04:39:02
如何获得访问令牌?
2021-04-18 04:39:02
access_token 来自 FB.login() 响应
2021-04-26 04:39:02
今天这对我有用。不知道这种情况会持续多久。可能与任何记录在案的功能一样可靠。:)
2021-04-30 04:39:02
这有效,但我有点担心,url因为它似乎没有记录。但那么少。
2021-05-10 04:39:02

照片可以使用 Ajax 上传到 facebook 个人资料,如下所示。

$.ajax({
            type: "POST",
            url: "https://graph.facebook.com/me/photos",
            data: {
                message: "Your Msg Goes Here",
                url: "http://www.knoje.com/images/photo.jpg[Replace with yours]",
                access_token: token,
                format: "json"
            },
            success: function(data){
               alert("POST SUCCESSFUL"); }
            });

所以这是使用 GRAPH API 将照片发布到 facebook 个人资料的最佳方式,而且是最简单的方式。

在许多答案中,我看到图像 url 是由来源、图片或图像等提供的,但这不起作用。

使用源、图片或图像会导致(#324) 需要上传文件错误。

避免 324 错误的最佳方法。

根据 fb api,您必须指定要发布的图像的 url,您可以尝试提供图像的本地路径,以防万一。
2021-04-16 04:39:02
如果你想上传本地图片怎么办?(即,图像在您的手机/计算机中,而不是在其他地方托管)
2021-04-21 04:39:02

只有@Thiago 的回答是回答通过 javascript上传数据的问题我发现 Facebook JS API 没有涵盖这种情况。

我还酿造并测试了我的个人解决方案。

主要步骤

  1. 获取图像的二进制数据(我使用了画布,但也可以使用输入框)
  2. 使用图形 API 调用的所有必要数据形成多部分请求
  3. 在请求中包含二进制数据
  4. 将所有内容编码为二进制数组并通过 XHR 发送

代码

转换实用程序

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

图片发布片段

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);
};

用法

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
  }
});

额外的

提取画布图像的二进制字符串表示

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);
}

有关如何从 input[type=file]

HTML5 文件 API 读取为文本和二进制

笔记:

  1. 当然也有替代方法
    • 在 iframe 中使用 HTML 表单 - 您无法从调用中获得响应
    • 使用FormData&File方法,但不幸的是,在这种情况下,有很多不兼容性使该过程更难使用,并且您最终会围绕不一致性进行管道录音 - 因此我的选择是手动数据组装,因为 HTTP 标准很少改变:)
  2. 该解决方案不需要任何特殊的 HTML5 功能。
  3. 上面的例子使用jQuery.ajax, jQuery.extend,jQuery.each
这是我从桌面上传文件并发布的唯一方法,非常感谢。
2021-04-24 04:39:02