it-swarm.com.de

Facebook Graph API - Foto mit JavaScript hochladen

Ist es möglich, eine Datei mit der Facebook Graph-API mit Javascript hochzuladen, fühle ich mich nahe. Ich benutze das folgende 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!');
        }
    }); 
}

Nach dem Ausführen erhalte ich die folgende Fehlermeldung ...

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

Wenn ich versuche, diese Methode zu erforschen, kann ich nur herausfinden, dass es eine PHP-Methode ist, die dies zu lösen scheint

$facebook->setFileUploadSupport(true);

Ich verwende jedoch JavaScript. Diese Methode scheint mit den Berechtigungen von Facebook Graph zu tun zu haben, aber ich habe bereits die Berechtigungen user_photos und publish_stream gesetzt, von denen ich glaubte, dass sie die einzigen sind, die ich für diesen Vorgang benötigen sollte.

Ich habe ein paar unbeantwortete Fragen dazu zu Stackoverflow gesehen, hoffentlich kann ich mich selbst genug erklären. Danke Leute.

40
Moz

EDIT: Diese Antwort ist (jetzt) ​​weitgehend irrelevant. Wenn sich Ihr Bild im Web befindet, geben Sie einfach den Parameter url gemäß API an (und sehen Sie Beispiele in anderen Antworten). Wenn Sie POST den Bildinhalt direkt auf Facebook speichern möchten, möchten Sie möglicherweise diese Antwort lesen, um Verständnis zu erlangen. Siehe auch HTML5's Canvas.toDataUrl().

Die API sagt : "Um ein Foto zu veröffentlichen, stellen Sie eine POST Anforderung mit dem Dateianhang als Multipart-/Formulardaten ab."

FB erwartet, dass sich die Bytes des Bildes, das hochgeladen werden soll, im Rumpf der HTTP-Anforderung befinden, sie sind jedoch nicht vorhanden. Oder um es anders anzuschauen - woher liefern Sie im FB.api () - Aufruf den eigentlichen Inhalt des Bildes? 

Die FB.api () API ist schlecht dokumentiert und liefert kein Beispiel für ein HTTP POST, das einen Body enthält. Man kann aus dem Fehlen eines solchen Beispiels schließen, dass es dies nicht unterstützt.

Das ist wahrscheinlich in Ordnung - FB.api () verwendet etwas namens XmlHttpRequest unter den Covers, das unterstützt, einschließlich eines Körpers ... in Ihrer bevorzugten JavaScript-Referenz nachschlagen.

Sie haben jedoch noch zwei Unterprobleme zu lösen:

  1. wie man die Bildbytes (und den Rest der Anforderung) als multipart/form-data vorbereitet; und
  2. holen Sie sich die Bytes des Bildes selbst

(Übrigens ist es wahrscheinlich die Notwendigkeit, den Nachrichtentext zu codieren, wofür die PHP setFileUploadSupport (true) -Methode bestimmt ist - das facebook-Objekt muss den Nachrichtentext vor dem Senden als multipart/form-data codieren.

Aber es ist ein bisschen mehr als das

Leider kann das Unterproblem '2' Sie beißen - es gibt keine Möglichkeit (das letzte Mal, als ich nachgesehen habe), um die Bytes eines Bildes aus dem vom Browser bereitgestellten Image-Objekt zu extrahieren. 

Wenn das hochzuladende Bild über eine URL erreichbar ist, können Sie die Bytes mit XmlHttpRequest abrufen. Nicht so schlecht.

Wenn das Bild vom Desktop des Benutzers stammt, können Sie dem Benutzer wahrscheinlich folgendes bieten:

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

(Beachten Sie, dass source auf den Namen verweist, der dem Widget für das Hochladen von Dateien zugewiesen wurde.)

... und hoffen, dass der FB die Daten auf diese Weise erhalten hat (versuchen Sie es zuerst mit einem statischen HTML-Formular, bevor Sie sie in JS dynamisch codieren). Man könnte daraus schließen, dass dies tatsächlich der Fall wäre, da sie keine andere Möglichkeit bieten, dies zu tun.

26
David Bullock

Ja, das ist möglich, ich finde 2 Lösungen, wie man das macht, und sie sind sich sehr ähnlich

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

});

und ZWEITER mit jQuery Post-Anfrage und 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");
                    }
                });

ich habe @ Владимир Дворник mit einigen Modifikationen verwendet.

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

        });
17
Arrabi

Fotos können mit Ajax wie folgt auf Facebook-Profil hochgeladen werden.

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

Dies ist der beste Weg, um Fotos mit der GRAPH-API in einem Facebook-Profil zu veröffentlichen. Dies ist die einfache Methode.

In vielen Antworten habe ich gesehen, dass die Bild-URL von der Quelle, dem Bild oder Bild usw. angezeigt wird, aber das funktioniert nicht. 

Die Verwendung von Quelle, Bild oder Bild führt zu einem (# 324) Erfordert Upload-Datei Fehler.

Der beste Weg, um den Fehler 324 zu vermeiden.

11
sumitkanoje

Nur die Antwort von @ Thiago beantwortet die Frage von uploading -Daten über Javascript. Ich habe festgestellt, dass die Facebook JS API diese Situation nicht abdeckt. 

Ich habe auch meine persönliche Lösung gebraut und getestet. 

Hauptschritte

  1. Holen Sie sich die Binärdaten des Bildes (Ich habe eine Leinwand verwendet, aber auch ein Eingabefeld ist möglich)
  2. Bilden Sie eine mehrteilige Anforderung mit allen erforderlichen Daten für den Graph-API-Aufruf
  3. Fügen Sie die binären Daten in die Anforderung ein
  4. Kodiere alles in einem binären Array und sende es so per XHR

Code

Konvertierungsprogramme

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

Bildausschnitt-Ausschnitt

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

Verwendungszweck

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

Extrahieren der binären Zeichenfolgendarstellung eines Leinwandbildes

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

Informationen zum Laden des binaryString aus einem input[type=file]

HTML5-Datei-API als Text und binär gelesen

Anmerkungen:

  1. Es gibt natürlich auch alternative Ansätze
    • Verwenden eines HTML-Formulars in einem iframe - Sie können keine Antwort vom Anruf erhalten
    • Mit einem FormData & File -Ansatz, aber in diesem Fall gibt es leider viele Inkompatibilitäten, die den Prozess schwieriger machen, und Sie würden die Inkonsistenzen mit einem Kanonen-Taping enden manuelle Datenmontage, da sich HTTP-Standards selten ändern :)
  2. Die Lösung erfordert keine speziellen HTML5-Funktionen.
  3. Das obige Beispiel verwendet jQuery.ajax , jQuery.extend , jQuery.each
6
Matyas

Ja, Sie können diese Buchungsdaten in einem iframe wie hier eingeben, oder Sie können jQuery File Upload .. verwenden ein Seitengriff.

Beispiel: Laden Sie ein Video mit jQuery File Upload hoch

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

Um eine Datei vom lokalen Computer aus mit nur Javascript hochzuladen, versuchen Sie 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>

Es gibt eine Upload-Demo unter http://adodson.com/hello.js/demos/upload.html

2
Drew

https://stackoverflow.com/a/16439233/68210 enthält eine Lösung, die funktioniert, wenn Sie die Fotodaten selbst hochladen möchten und keine URL haben.

2
Daniel X Moore

Das funktioniert:

   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);
};
2
Thiago Tecedor

Das funktioniert immer noch. Ich benutze es wie folgt:

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

Ich muss allerdings fragen, ob Sie wissen, ob dies ratsam ist oder ein großes Sicherheitsrisiko im Vergleich zur Verwendung von PHP für Facebook aufweist.

2
Carmela

Ich habe scheinbar ein ähnliches Problem, aber die obigen Lösungen haben nicht funktioniert.

Ich habe die von Arrabi vorgeschlagene Lösung verwendet (verwenden Sie nur die URL-Eigenschaft), um Bilder problemlos zu veröffentlichen. Meine Bilder sind jeweils 2-3 MB groß.

Bei der Migration meiner App auf einen anderen Server (Ändern der absoluten URL meiner Bilder in der Veröffentlichung) gab mir die Methode immer 324 Fehler für Bilder mit einer Größe von mehr als 100 KB.

Ich dachte, es liegt an einer Apache-Einstellung an meinem Ende, aber als ich Apache für lighttpd änderte, war das Problem immer noch da.

Die Verbindungen von Facebook werden tatsächlich in meinem (Apache-) Protokoll angezeigt:

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: // entwickler .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) "

Nur test2.png war erfolgreich.

1
Tom Lous

Ich verwende Folgendes zum Freigeben eines Fotos (einige BitmapData aus dem Phaser-Framework). Es scheint zu funktionieren ...

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

Falls noch jemand nach dem Upload von direkt von der Leinwand auf Facebook-Fotos sucht, funktioniert das für mich:

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

Um es zu benutzen

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

Modifiziert von: http://gorigins.com/posting-a-canvas-image-to-facebook-and-Twitter/

0
aunnnn