Facebook Graph API - загрузка фотографий с использованием JavaScript
Можно ли загрузить файл с помощью API-интерфейса Facebook, используя javascript, я чувствую, что я рядом. Я использую следующий 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, надеюсь, я могу объяснить себя достаточно. Спасибо, ребята.
Ответы
Ответ 1
EDIT: этот ответ (сейчас) в значительной степени не имеет значения. Если ваше изображение находится в Интернете, просто укажите параметр url
в соответствии с API (и см. Примеры в других ответах). Если вы хотите, чтобы POST-контент был напрямую связан с facebook, вы можете прочитать этот ответ, чтобы получить понимание. Также см. HTML5 Canvas.toDataUrl()
.
API говорит: "Чтобы опубликовать фотографию, отправьте запрос POST с прикрепленным файлом фото в формате multipart/form-data".
FB ожидает, что байты загружаемого изображения находятся в теле HTTP-запроса, но их там нет. Или посмотреть на это по-другому - где в вызове FB.api() вы загружаете фактическое содержимое самого изображения?
API FB.api() плохо документирован и не предоставляет пример HTTP POST, который включает тело. Из отсутствия такого примера можно сделать вывод, что он не поддерживает это.
Скорее всего, OK - FB.api() использует что-то под названием XmlHttpRequest
под обложками, которое поддерживает, включая тело,... посмотрите его в своей любимой ссылке на JavaScript.
Однако у вас все еще есть 2 проблемы:
- как подготовить байты изображения (и остальную часть запроса) как multipart/form-data; и
- получение байтов самого изображения
(кстати, необходимость кодирования тела сообщения, вероятно, является методом 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). Можно было бы сделать вывод, что на самом деле это было бы, поскольку они не предлагают другого средства для этого.
Ответ 2
Да, это возможно, я нахожу 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 request и 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");
}
});
Ответ 3
я использовал код @Владимир Дворник с некоторой модификацией, у меня была такая же проблема, и с этим кодом он работал очень хорошо:
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);
}
});
Ответ 4
Фотографии можно загрузить в профиль facebook с помощью Ajax следующим образом.
$.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"); }
});
Итак, это лучший способ отправить фотографию в профиль facebook с помощью GRAPH API и является простым.
Во многих ответах я видел, что URL изображения является shwon источником, изображением или изображением и т.д., но это не работает.
Использование источника, изображения или изображения приводит к (# 324) Требуется загрузить файл.
Лучший способ избежать ошибки 324.
Ответ 5
Только ответ @Thiago отвечает на вопрос о загрузке данных через javascript. Я обнаружил, что API JS для Facebook не охватывает эту ситуацию.
У меня также есть brew и проверено мое решение personl.
Основные шаги
- Получить двоичные данные изображения (я использовал холст, но также можно использовать поле ввода)
- Формируйте многостраничный запрос со всеми необходимыми данными для вызова API-интерфейса графика
- Включить двоичные данные в запрос
- Кодировать все в двоичном массиве и отправлять его через 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
}
});
Extra
Извлечение двоичного строкового представления изображения холста
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]
API-интерфейс HTML5 читается как текстовый и двоичный
Примечания:
- Есть, конечно, альтернативные подходы
- Использование формы HTML в iframe - вы не можете получить ответ от вызова
- Использование
FormData
и File
, но, к сожалению, в этом случае есть много несовместимостей, которые усложняют процесс, и вы в конечном итоге обходите каналограмму вокруг несоответствий - таким образом, мой выбор был ручной сборкой данных, поскольку стандарты HTTP редко меняются:)
- Решение не требует специальных функций HTML5.
- В приведенном выше примере используется
jQuery.ajax
, jQuery.extend
, jQuery.each
Ответ 6
Да, вы можете сделать эти данные для отправки в iframe, например здесь, или вы можете использовать Загрузка файла jQuery.
Проблема в том, что вы не можете получить ответ от iframe, используя плагин, вы можете использовать дескриптор страницы.
Пример: загрузка видео с помощью загрузки файла jQuery
<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>
Ответ 7
Чтобы загрузить файл с локального компьютера с помощью 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
Ответ 8
fooobar.com/questions/7100/... содержит решение, которое работает, если вам нужно загрузить сами фотографии и не иметь URL-адреса.
Ответ 9
Это все еще работает. Я использую его, как показано ниже:
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);
}
Я должен спросить, если у вас есть идеи, если это целесообразно или имеет большой риск для безопасности по сравнению с использованием PHP api для Facebook.
Ответ 10
Это работает:
function x(authToken, filename, mimeType, imageData, message) {
// this is the multipart/form-data boundary we'll use
var boundary = '----ThisIsTheBoundary1234567890';
// let 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);
};
Ответ 11
У меня, похоже, есть аналогичная проблема, но решения выше не работают.
Я использовал решение, предложенное Arrabi (просто используйте свойство url), чтобы отправлять изображения без каких-либо проблем. Мои изображения составляют около 2-3 МБ каждый.
Когда я перенес свое приложение на другой сервер (изменив абсолютный URL-адрес моих изображений в сообщении), метод продолжал давать мне 324 ошибки для изображений размером около 100 тыс..
Я думал, что это связано с некоторыми настройками Apache на моем конце, но когда я изменил apache для lighttpd, проблема все еще была.
Связи из Facebook фактически отображаются в моем (apache) журнале:
69.171.234.7 - - [08/Июнь/2012: 11: 35: 54 +0200] "GET/images/cards/1337701633_518192458.png HTTP/1.1" 200 2676608 "-" "facebookplatform/1.0 (+ http://developers.facebook.com)"
69.171.228.246 - - [08/Июнь/2012: 11: 42: 59 +0200] "GET/images/test5.jpg HTTP/1.1" 200 457402 "-" "facebookplatform/1.0 (+ http://developers.facebook.com)"
69.171.228.246 - - [08/Июнь/2012: 11: 43: 17 +0200] "GET/images/test4.jpg HTTP/1.1" 200 312069 "-" "facebookplatform/1.0 (+ http://developers.facebook.com)"
69.171.228.249 - - [08/Июнь/2012: 11: 43: 49 +0200] "GET/images/test2.png HTTP/1.1" 200 99538 "-" "facebookplatform/1.0 (+ http://developers.facebook.com)"
69.171.228.244 - - [08/Июнь/2012: 11: 42: 31 +0200] "GET/images/test6.png HTTP/1.1" 200 727722 "-" "facebookplatform/1.0 (+ http://developers.facebook.com)"
Выполнено только test2.png.
Ответ 12
Я использую следующее, чтобы поделиться фотографией (некоторые 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);
}
Ответ 13
В случае, если кто-то еще ищет, как загружать прямо из холста на фотографии Facebook, это работает для меня:
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'});
}
Использовать его
// *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});
}
});
Изменено: http://gorigins.com/posting-a-canvas-image-to-facebook-and-twitter/