Facebook Graph API - 使用 JavaScript 上传照片
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4999024/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Facebook Graph API - upload photo using JavaScript
提问by Moz
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
是否可以使用 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!');
}
});
}
Upon running this I receive the following error...
运行此程序后,我收到以下错误...
"OAuthException" - "(#324) Requires upload file"
When I try and research this method all I can find out about is a php method that apears to solve this
当我尝试研究这种方法时,我只能找到一种可以解决此问题的 php 方法
$facebook->setFileUploadSupport(true);
However, I am using JavaScript, it looks like this method might be to do with Facebook Graph permissions, but I already have set the permissions user_photos and publish_stream, which I believed are the only ones I should need to perform this operation.
但是,我使用的是 JavaScript,看起来这种方法可能与 Facebook Graph 权限有关,但我已经设置了权限 user_photos 和 publish_stream,我认为这是执行此操作所需的唯一权限。
I have seen a couple of unanswered questions regarding this on stackoverflow, hopefully I can explained myself enough. Thanks guys.
我在 stackoverflow 上看到了几个与此相关的悬而未决的问题,希望我能对自己进行足够的解释。谢谢你们。
采纳答案by David Bullock
EDIT: this answer is (now) largely irrelevant. If your image is on the web, just specify the
url
param as per the API(and see examples in other answers). If you would like to POST the image content to facebook directly, you may want to read this answer to gain understanding. Also see HTML5'sCanvas.toDataUrl()
.
编辑:这个答案(现在)在很大程度上无关紧要。如果您的图像在网络上,只需
url
根据API指定参数(并查看其他答案中的示例)。如果您想直接将图像内容发布到 facebook,您可能需要阅读此答案以获取理解。另请参阅 HTML5 的Canvas.toDataUrl()
.
The API says: "To publish a photo, issue a POST request with the photo file attachment as multipart/form-data."
API说:“要发布照片,请将照片文件附件作为 multipart/form-data发出 POST 请求。”
FB is expecting that the bytes of the image to be uploaded are in the body of the HTTP request, but they're not there. Or to look at it another way - where in the FB.api() call are you supplying the actual contents of the image itself?
FB 期望要上传的图像字节在 HTTP 请求的正文中,但它们不在那里。或者以另一种方式看待它 - 您在 FB.api() 调用中的哪个位置提供图像本身的实际内容?
The FB.api()API is poorly documented, and doesn't supply an example of an HTTP POST which includes a body. One might infer from the absence of such an example that it doesn't support this.
所述FB.api()API记录不当,并且不提供的HTTP POST,其包括主体的一个例子。人们可能会从没有这样一个例子中推断出它不支持这一点。
That's probably OK - FB.api() is using something called XmlHttpRequest
under the covers which doessupport including a body ... look it up in your favourite JavaScript reference.
这可能没问题 - FB.api() 正在使用一些称为undercovers 的东西XmlHttpRequest
,它确实支持包含一个主体......在你最喜欢的 JavaScript 参考中查找它。
However, you'll still have 2 sub-problems to solve:
但是,您仍然需要解决 2 个子问题:
- how to prepare the image bytes (and rest of the request) as multipart/form-data; and
- getting the bytes of the image itself
- 如何将图像字节(以及请求的其余部分)准备为multipart/form-data;和
- 获取图像本身的字节
(incidentally, the need to encode the message body is probably what the PHP setFileUploadSupport(true) method is for - tell the facebook
object to encode the message body as multipart/form-data
before sending)
(顺便说一句,对消息正文进行编码的需要可能是 PHP setFileUploadSupport(true) 方法的用途 - 告诉facebook
对象multipart/form-data
在发送之前对消息正文进行编码)
But it's a bit meessier than that
但它比那更混乱
Unfortunately, sub-problem '2' may bite you - there is no way (last time I looked) to extract the bytes of an image from the browser-supplied Image object.
不幸的是,子问题 '2' 可能会咬你 - 没有办法(我上次看)从浏览器提供的 Image 对象中提取图像的字节。
If the image to be uploaded is accessible via a URL, you could fetch the bytes with XmlHttpRequest. Not too bad.
如果可以通过 URL 访问要上传的图像,则可以使用 XmlHttpRequest 获取字节。还不错。
If the image is coming from the user's desktop, your probable recourse is to offer the user a:
如果图像来自用户的桌面,您可能的方法是为用户提供:
<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>
(notice that source
references the name given to the file-upload widget)
(注意source
引用了文件上传小部件的名称)
... and hope that FB anticipated receiving the data in this manner (try it with a static HTML form first, before coding it up dynamically in JS). One might infer that in fact it would, since they don't offer another means of doing it.
...并希望 FB 预期以这种方式接收数据(先尝试使用静态 HTML 表单,然后再在 JS 中对其进行动态编码)。人们可能会推断,事实上它会,因为他们没有提供另一种方法来做到这一点。
回答by Владимир Дворник
Yes, this is possible, i find 2 solutions how to do that and they are very similar to each other, u need just define url parameter to external image url
是的,这是可能的,我找到了 2 个解决方案,它们彼此非常相似,您只需将 url 参数定义为外部图像 url
FIRST one using Javascript SDk:
第一个使用 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);
}
});
and SECOND one using jQuery Post request and FormData:
并使用第二个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");
}
});
回答by Arrabi
i used @Владимир Дворник code with some modification, I had the same issue and with this code it worked very well:
我使用了@Владимир Дворник 代码并进行了一些修改,我遇到了同样的问题,并且使用此代码效果很好:
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);
}
});
回答by sumitkanoje
Photos can be uploaded to facebook profile using Ajax as follows.
照片可以使用 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"); }
});
So this is the best way to post photo to a facebook profile with GRAPH API and is the simple one.
所以这是使用 GRAPH API 将照片发布到 facebook 个人资料的最佳方式,而且是最简单的方式。
In many answer i have seen that image url is shwon by the source,picture or image etc but that doesn't works.
在许多答案中,我看到图像 url 是由来源、图片或图像等提供的,但这不起作用。
The use of of source,picture or image leads to a (#324) Requires upload fileerror .
使用源、图片或图像会导致(#324) 需要上传文件错误。
Best way to avoid the 324 error.
避免 324 错误的最佳方法。
回答by Matyas
Only @Thiago's answer is answering the question of uploadingdata via javascript. I've found that the Facebook JS API doesn't cover this situation.
只有@Thiago 的回答是回答通过 javascript上传数据的问题。我发现 Facebook JS API 没有涵盖这种情况。
I've also brew & tested my personl solution.
我还酿造并测试了我的个人解决方案。
Main steps
主要步骤
- Get the binary data of the image (I've used a canvas, but using an input box is possible as well)
- Form a multipart request with all necesarry data for the graph API call
- Include the binary data in the request
- Encode everything in a binary array and send it so via XHR
- 获取图像的二进制数据(我使用了画布,但也可以使用输入框)
- 使用图形 API 调用的所有必要数据形成多部分请求
- 在请求中包含二进制数据
- 将所有内容编码为二进制数组并通过 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]
有关如何从 input[type=file]
HTML5 File API read as text and binary
Notes:
笔记:
- 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 :)
- The solution does not require any special HTML5 features.
- The above example uses
jQuery.ajax
,jQuery.extend
,jQuery.each
- 当然也有替代方法
- 该解决方案不需要任何特殊的 HTML5 功能。
- 上面的例子使用
jQuery.ajax
,jQuery.extend
,jQuery.each
回答by Guilherme Torres Castro
Yes, you can do this posting data to an iframe like here, or you can use jQuery File Upload. The problem is you can't get response from iframe, using plugin you can use a page handle.
是的,您可以像这里一样将数据发布到 iframe ,或者您可以使用jQuery File Upload。问题是您无法从 iframe 获得响应,使用插件您可以使用页面句柄。
Example: upload a video using jQuery File Upload
示例:使用 jQuery File Upload 上传视频
<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>
回答by Drew
To upload a file from the local computer with just Javascript try HelloJS
要仅使用 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>
There's an upload demo at http://adodson.com/hello.js/demos/upload.html
回答by Daniel X Moore
https://stackoverflow.com/a/16439233/68210contains a solution that works if you need to upload the photo data itself and don't have a url.
https://stackoverflow.com/a/16439233/68210包含一个解决方案,如果您需要上传照片数据本身并且没有网址,则该解决方案有效。
回答by Carmela
This still works. I am using it as below:
这仍然有效。我使用它如下:
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://images/image.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);
}
I have to ask though if you people have any idea if this is advisable or has a big security risk compared to using PHP api for Facebook.
不过,我不得不问一下,与将 PHP api 用于 Facebook 相比,你们是否知道这是否可取或具有很大的安全风险。
回答by Thiago Tecedor
This works:
这有效:
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);
};