page open fan javascript facebook facebook-graph-api file-upload

javascript - open - publish on facebook api



Facebook Graph API: sube una foto usando JavaScript (13)

EDITAR: esta respuesta es (ahora) en gran medida irrelevante. Si su imagen está en la web, simplemente especifique el parámetro de url según la API (y vea ejemplos en otras respuestas). Si desea enviar el contenido de la imagen directamente a Facebook, le recomendamos que lea esta respuesta para obtener más información. También vea Canvas.toDataUrl() HTML5.

La API API : "Para publicar una foto, emita una solicitud POST con el archivo adjunto de foto como multipart / form-data ".

FB espera que los bytes de la imagen que se cargarán estén en el cuerpo de la solicitud HTTP, pero no están allí. O para verlo de otra manera, ¿en qué parte de la llamada FB.api () está suministrando el contenido real de la imagen?

La API FB.api() está poco documentada y no proporciona un ejemplo de HTTP POST que incluye un cuerpo. Uno podría inferir de la ausencia de tal ejemplo que no es compatible con esto.

Probablemente eso esté bien: FB.api () está utilizando algo llamado XmlHttpRequest bajo las carátulas, que admite incluir un cuerpo ... búsquelo en su referencia de JavaScript favorita.

Sin embargo, todavía tendrá 2 sub-problemas para resolver:

  1. cómo preparar los bytes de la imagen (y el resto de la solicitud) como multipart/form-data ; y
  2. obteniendo los bytes de la imagen

(Incidentalmente, la necesidad de codificar el cuerpo del mensaje es probablemente para lo que es el método PHP setFileUploadSupport (true): indicar al objeto facebook que codifique el cuerpo del mensaje como multipart/form-data antes de enviarlo)

Pero es un poco más absurdo que eso

Desafortunadamente, el sub-problema "2" puede morderte: no hay forma (la última vez que lo busqué) de extraer los bytes de una imagen del objeto Imagen proporcionado por el navegador.

Si la imagen que se va a cargar es accesible a través de una URL, puede buscar los bytes con XmlHttpRequest. No está mal.

Si la imagen proviene del escritorio del usuario, su posible recurso es ofrecer al usuario un:

<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>

(observe que la source referencia al nombre dado al widget de carga de archivos)

... y espero que FB anticipó recibir los datos de esta manera (primero pruébelo con un formulario HTML estático antes de codificarlo dinámicamente en JS). Se podría inferir que de hecho lo sería, ya que no ofrecen otro medio para hacerlo.

¿Es posible cargar un archivo usando la API Graph de Facebook usando JavaScript? Siento que estoy cerca. Estoy usando el siguiente 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!''); } }); }

Al ejecutar esto recibo el siguiente error ...

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

Cuando intento investigar este método, todo lo que puedo averiguar es un método php que parece resolver este problema.

$facebook->setFileUploadSupport(true);

Sin embargo, estoy usando JavaScript, parece que este método podría tener que ver con los permisos de Facebook Graph, pero ya he establecido los permisos user_photos y publish_stream, que creo que son los únicos que debería necesitar para realizar esta operación.

He visto un par de preguntas sin respuesta con respecto a esto en stackoverflow, espero poder explicarlo lo suficiente. Gracias chicos.


En caso de que alguien esté buscando cómo cargar directamente desde el lienzo a las fotos de Facebook , esto funciona para mí:

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

Para usarlo

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

Modificado de: http://gorigins.com/posting-a-canvas-image-to-facebook-and-twitter/


Esto todavía funciona Lo estoy usando de la siguiente manera:

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

Sin embargo, tengo que preguntar si ustedes tienen alguna idea de si esto es aconsejable o si tiene un gran riesgo de seguridad en comparación con el uso de PHP api para Facebook.


La única respuesta de @Tiago es responder la pregunta de subir datos a través de javascript. Descubrí que la API de Facebook JS no cubre esta situación.

También he preparado y probado mi solución personal.

Pasos principales

  1. Obtenga los datos binarios de la imagen (he usado un lienzo, pero también es posible usar un cuadro de entrada)
  2. Formule una solicitud de varias partes con todos los datos necesarios para la llamada gráfica API
  3. Incluir los datos binarios en la solicitud
  4. Codifica todo en una matriz binaria y envíalo así a través de XHR

Código

Utilidades de conversión

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

Fragmento de publicación de imagen

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

Uso

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

Extracción de la representación de cadena binaria de una imagen de lienzo

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

Información sobre cómo cargar binaryString desde una input[type=file]

HTML5 File API leer como texto y binario

Notas:

  1. Por supuesto, hay enfoques alternativos
    • Usar un formulario HTML en un iframe: no puede obtener la respuesta de la llamada
    • Usar un enfoque de FormData y File , pero desafortunadamente en este caso hay muchas incompatilidades que hacen que el proceso sea más difícil de usar, y usted terminaría pegando cintas alrededor de las inconsistencias, así que mi elección fue el ensamblaje manual de datos ya que las normas HTTP rara vez cambian :)
  2. La solución no requiere funciones HTML5 especiales.
  3. El ejemplo anterior usa jQuery.ajax , jQuery.extend , jQuery.each

Para cargar un archivo desde la computadora local con solo Javascript, pruebe 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>

Hay una demostración de carga en http://adodson.com/hello.js/demos/upload.html


Parece que tengo un problema similar, pero las soluciones anteriores no funcionaron.

Estaba usando la solución sugerida por Arrabi (solo use la propiedad url) para publicar imágenes sin ningún problema. Mis imágenes son alrededor de 2-3 MB cada una.

Cuando migré mi aplicación a otro servidor (cambiando la URL absoluta de mis imágenes en la publicación), el método me siguió dando 324 errores para imágenes de un tamaño superior a 100k.

Pensé que se debía a algún ajuste de Apache en mi extremo, pero cuando cambié apache para lighttpd el problema todavía estaba allí.

Las conexiones de Facebook en realidad aparecen en mi registro (apache):

69.171.234.7 - - [08 / Jun / 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 / jun / 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 / jun / 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 / jun / 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 / jun / 2012: 11: 42: 31 +0200] "GET /images/test6.png HTTP / 1.1" 200 727722 "-" "facebookplatform / 1.0 (+ http: //developers.facebook .com) "

Solo test2.png tuvo éxito.


Sí, esto es posible, encuentro 2 soluciones para hacer eso y son muy similares entre sí, solo necesita definir el parámetro url a url de imagen externa

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

y SEGUNDO usando la solicitud de jQuery Post y 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"); } });


Sí, puede hacer esto publicando datos en un iframe como here , o puede usar jQuery File Upload . El problema es que no se puede obtener una respuesta de iframe, con el uso de un plugin puedes usar un manejador de página.

Ejemplo: cargar un video usando 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>


Uso lo siguiente para compartir una foto (algunos BitmapData del marco Phaser). Parece funcionar...

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


utilicé el código de @VladyMedia con algunas modificaciones, tuve el mismo problema y con este código funcionó muy bien:

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


Esto funciona:

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


Las fotos se pueden subir al perfil de Facebook usando Ajax de la siguiente manera.

$.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"); } });

Así que esta es la mejor manera de publicar fotos en un perfil de Facebook con GRAPH API y es la más simple.

En muchas respuestas, he visto que la url de la imagen se muestra por la fuente, imagen o imagen, etc. pero eso no funciona.

El uso de fuente, imagen o imagen conduce a un (# 324) Requiere error de archivo de carga .

La mejor manera de evitar el error 324.


https://.com/a/16439233/68210 contiene una solución que funciona si necesita cargar los datos de la foto y no tiene una url.