Facebook Graph API – 使用JavaScript上传照片

是否有可能使用JavaScript上传使用FacebookgraphicsAPI的文件,我觉得我很接近。 我正在使用下面的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" 

当我尝试和研究这个方法时,我所能find的是一个可以解决这个问题的php方法

 $facebook->setFileUploadSupport(true); 

不过,我正在使用JavaScript,它看起来像这个方法可能是与Facebook Graph权限,但我已经设置了权限user_photos和publish_stream,我相信是我应该需要执行此操作的唯一的。

我已经看到了几个关于这个在stackoverflow上没有回答的问题,希望我可以解释自己。 多谢你们。

编辑:这个答案是(现在)在很大程度上不相关。 如果您的图片位于networking上,只需按照API指定url参数(并参阅其他答案中的示例)。 如果您想直接将图像内容发布到Facebook,您可能需要阅读此答案以获得理解。 另请参阅HTML5的Canvas.toDataUrl()

该API 说 :“要发布一张照片,发出一个带有照片文件附件的POST请求作为multipart / form-data

FB期望要上载的图像的字节在HTTP请求的主体中,但是它们不在那里。 或者以另一种方式来看待它 – 在FB.api()调用中,您提供图像本身的实际内容?

FB.api() APIlogging不完整,不提供包含主体的HTTP POST示例。 从没有这样的例子可以推断,它不支持这个。

这可能是确定的 – FB.api()在封面下使用了一些名为XmlHttpRequest东西, 支持包括一个主体…查看你最喜欢的JavaScript引用。

不过,你仍然有两个子问题需要解决:

  1. 如何将图像字节(以及其余的请求)准备为多部分/表单数据 ; 和
  2. 获取图像本身的字节

(顺便说一下,编码消息正文的需要可能是PHP setFileUploadSupport(true)方法的用途 – 告诉facebook对象在发送之前将消息正文编码为multipart/form-data

但是比这更有趣

不幸的是,子问题'2'可能咬你 – 没有办法(上次我看)从浏览器提供的图像对象提取图像的字节。

如果要上传的图像可以通过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引用了file upload小部件的名称)

…并希望FB预期以这种方式接收数据(先用静态HTML表单试用,然后再用JSdynamic编码)。 有人可能会推断,实际上,因为他们没有提供另一种手段。

是的,这是可能的,我find了2个解决scheme如何做到这一点,他们是非常相似的,你只需要定义url参数外部图像url

第一个使用Javascript SDK:

 var imgURL="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="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"); } }); 

我用@ВладимирДворник代码进行了一些修改,我有同样的问题,并与此代码工作得很好:

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

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

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

所以这是使用GRAPH API将照片发布到Facebook个人资料的最好方法,也是最简单的一种。

在很多答案中,我已经看到,图像的URL是由源,图片或图像等,但不起作用。

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

最好的方法来避免324错误。

只有@ Thiago的答案是回答通过JavaScript 上传数据的问题。 我发现Facebook的JS API不包括这种情况。

我也酿造和testing了我的个人解决scheme。

主要步骤

  1. 获取图像的二进制数据(我使用了canvas,但也可以使用input框)
  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 } }); 

额外

提取canvas图像的二进制string表示

 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]加载binaryString的信息input[type=file]

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

笔记:

  1. 当然也有替代方法
    • 在iframe中使用HTML表单 – 您无法从调用中获得响应
    • 使用FormDataFile方法,但不幸的是,在这种情况下,会有很多不兼容的情况使得这个过程更难使用,而且最终会导致不一致的问题 – 因此,我的select是手动数据组装,因为HTTP标准很less改变:)
  2. 该解决scheme不需要任何特殊的HTML5function。
  3. 上面的例子使用了jQuery.ajaxjQuery.extendjQuery.each

是的,你可以把这个发布数据做到像这里一样的iframe,或者你可以使用jQueryfile upload 。 问题是你无法从iframe获得响应,使用插件你可以使用页面句柄。

例如:使用jQuery File Upload上传video

 <form id="fileupload" action="https://graph-video.facebook.com/me/photos" method="POST" enctype="multipart/form-data"> <input type="hidden" name="acess_token" value="user_acess_token"> <input type="text" name="title"> <input type="text" name="description"> <input type="file" name="file"> <!-- name must be file --> </form> <script type="text/javascript"> $('#fileupload').fileupload({ dataType: 'json', forceIframeTransport: true, //force use iframe or will no work autoUpload : true, //facebook book response will be send as param //you can use this page to save video (Graph Api) object on database redirect : 'http://pathToYourServer?%s' }); </script> 

只需使用Javascript从本地计算机上传文件,请尝试HelloJS

 <form onsubmit="upload();"> <input type="file" name="file"/> <button type="submit">Submit</button> </form> <script> function upload(){ hello.api("facebook:/me/photos", 'post', document.getElementById('form'), function(r){ alert(r&&!r.error?'Success':'Failed'); }); } </script> 

http://adodson.com/hello.js/demos/upload.html有一个上传演示;

这仍然有效。 我正在使用它如下:

 var formdata= new FormData(); if (postAs === 'page'){ postTo = pageId; //post to page using pageID } formdata.append("access_token", accessToken); //append page access token if to post as page, uAuth|paAuth formdata.append("message", photoDescription); formdata.append("url", 'http:/http://img.dovov.comimage.png'); try { $.ajax({ url: 'https://graph.facebook.com/'+ postTo +'/photos', type: "POST", data: formdata, processData: false, contentType: false, cache: false, error: function (shr, status, data) { console.log("error " + data + " Status " + shr.status); }, complete: function () { console.log("Successfully uploaded photo to Facebook"); } }); } catch (e) { console.log(e); } 

我不得不问,如果你有任何想法,如果这是可取的或有一个很大的安全风险相比,使用Facebook的PHP API。

这工作:

  function x(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.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + boundary); // Solving problem with sendAsBinary for chrome try { if (typeof XMLHttpRequest.prototype.sendAsBinary == 'undefined') { XMLHttpRequest.prototype.sendAsBinary = function(text) { var data = new ArrayBuffer(text.length); var ui8a = new Uint8Array(data, 0); for (var i = 0; i < text.length; i++) ui8a[i] = (text.charCodeAt(i) & 0xff); this.send(ui8a); } } } catch (e) {} xhr.sendAsBinary(formData); }; 

我似乎有一个类似的问题,但上面的解决scheme不起作用。

我正在使用Arrabibuild议的解决scheme(只使用url属性)发布图像没有任何问题。 我的图像大约每个2-3 MB。

当我将我的应用程序迁移到另一台服务器(更改我的图像在文章中的绝对url),该方法不断给我以上约100k大小的图像324错误。

我认为这是由于我的一些Apache设置,但是当我改变了Apache的lighttpd问题仍然存在。

来自Facebook的连接实际上显示在我的(apache)日志中:

69.171.234.7 – – [08 / Jun / 2012:11:35:54 +0200]“GET http://img.dovov.comcards/1337701633_518192458.png HTTP / 1.1”200 2676608“ – ”“facebookplatform / 1.0(+ http:// developers .facebook.com)”

69.171.228.246 – [08 / Jun / 2012:11:42:59 +0200]“GET http://img.dovov.comtest5.jpg HTTP / 1.1”200 457402“ – ”“facebookplatform / 1.0(+ http://developers.facebook .COM)”

69.171.228.246 – [08 / Jun / 2012:11:43:17 +0200]“GET http://img.dovov.comtest4.jpg HTTP / 1.1”200 312069“ – ”“facebookplatform / 1.0(+ http://developers.facebook .COM)”

69.171.228.249 – [08 / Jun / 2012:11:43:49 +0200]“GET http://img.dovov.comtest2.png HTTP / 1.1”200 99538“ – ”“facebookplatform / 1.0(+ http://developers.facebook .COM)”

69.171.228.244 – [08 / Jun / 2012:11:42:31 +0200]“GET http://img.dovov.comtest6.png HTTP / 1.1”200 727722“ – ”“facebookplatform / 1.0(+ http://developers.facebook .COM)”

只有test2.png成功。

我使用以下来分享照片(Phaser框架中的一些BitmapData)。 这似乎工作…

 // Turn data URI to a blob ready for upload. dataURItoBlob(dataURI:string): Blob { 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' }); } // Share the given bitmapData as a photo on Facebook sharePhoto(accessToken: string, photo: BitmapData, message: string): void { // Create form data, set up access_token, source and message var fd = new FormData(); fd.append("access_token", accessToken); fd.append("source", this.dataURItoBlob(photo.canvas.toDataURL("image/jpeg"))); fd.append("message", message); var request = new XMLHttpRequest(); var thisPtr = this; request.onreadystatechange = function () { if (request.readyState == XMLHttpRequest.DONE) { var json = JSON.parse(request.responseText); if (json.hasOwnProperty("error")) { var error = json["error"]; if (error.hasOwnProperty("type")) { var errorType = error["type"]; if (errorType === "OAuthException") { console.log("Need to request more permissions!"); } } } } else if (request.readyState == XMLHttpRequest.HEADERS_RECEIVED) { } else if (request.readyState == XMLHttpRequest.LOADING) { } else if (request.readyState == XMLHttpRequest.OPENED) { } else if (request.readyState == XMLHttpRequest.UNSENT) { } } request.open("POST", "https://graph.facebook.com/me/photos", true); request.send(fd); }