Загрузить Base64 Image Facebook Graph API

Я пытаюсь загрузить образ base64 на страницу FaceBook с помощью Node.js. Мне удалось загрузить загрузку со всеми данными multipart и т.д., Если бы я прочитал файл из файловой системы (например, используя fs.readFileSync('c:\a.jpg))

Однако, если я использую кодированное изображение base64 и попробую загрузить его, он даст мне следующую ошибку: {"error":{"message":"(#1) An unknown error occurred","type":"OAuthException","code":1}}

Я попытался преобразовать его в двоичный файл new Buffer(b64string, 'base64'); и загрузить его, но не повезло.

Я боролся с этим в течение 3 дней, так что любая помощь была бы весьма признательна.

Изменить: если кто-то знает, как я могу преобразовать base64 в двоичный файл и успешно загрузить его, это также сработает для меня.

Изменить: фрагмент кода

var postDetails = separator + newlineConstant + 'Content-Disposition: form-data;name="access_token"' + newlineConstant + newlineConstant + accessToken + newlineConstant + separator;

postDetails = postDetails + newlineConstant + 'Content-Disposition: form-data; name="message"' + newlineConstant + newlineConstant + message + newlineConstant;

//Add the Image information
var fileDetailsString = '';
var index = 0;
var multipartBody = new Buffer(0);
images.forEach(function (currentImage) {
    fileDetailsString = fileDetailsString + separator + newlineConstant + 'Content-Disposition: file; name="source"; filename="Image' + index + '"' + newlineConstant + 'Content-Type: image/jpeg' + newlineConstant + newlineConstant;
    index++;

    multipartBody = Buffer.concat([multipartBody, new Buffer(fileDetailsString), currentImage]); //This is what I would use if Bianry data was passed in 

    currentImage = new Buffer (currentImage.toString('base64'), 'base64'); // The following lines are what I would use for base64 image being passed in (The appropriate lines would be enabled/disabled if I was using Binary/base64)
    multipartBody = Buffer.concat([multipartBody, new Buffer(fileDetailsString), currentImage]);
});

multipartBody = Buffer.concat([new Buffer(postDetails), multipartBody, new Buffer(footer)]);

Ответ 1

Приведенный выше код не совсем сработал у меня (пропуская запятую после type:"POST", и URI данных для сообщений о ошибках blob.Я получил следующий код для работы в Firefox и Chrome:

function PostImageToFacebook(authToken)
{
    var canvas = document.getElementById("c");
    var imageData  = canvas.toDataURL("image/png");
    try {
        blob = dataURItoBlob(imageData);
    }
    catch(e) {
        console.log(e);
    }
    var fd = new FormData();
    fd.append("access_token",authToken);
    fd.append("source", blob);
    fd.append("message","Photo Text");
    try {
        $.ajax({
            url:"https://graph.facebook.com/me/photos?access_token=" + authToken,
            type:"POST",
            data:fd,
            processData:false,
            contentType:false,
            cache:false,
            success:function(data){
                console.log("success " + data);
            },
            error:function(shr,status,data){
                console.log("error " + data + " Status " + shr.status);
            },
            complete:function(){
                console.log("Posted to facebook");
            }
        });
    }
    catch(e) {
        console.log(e);
    }
}

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

Здесь код в GitHub https://github.com/DanBrown180/html5-canvas-post-to-facebook-base64

Ответ 2

Надеюсь, это будет полезно. Выполняя загрузку фотографий в FB только с помощью javascript, вы можете использовать следующий метод. Требуемая вещь - это imageData (формат изображения base64) и тип mime.

try {
    blob = dataURItoBlob(imageData,mimeType);
} catch (e) {
    console.log(e);
}

var fd = new FormData();
fd.append("access_token",accessToken);
fd.append("source", blob);
fd.append("message","Kiss");

try {
   $.ajax({
        url:"https://graph.facebook.com/" + <<userID received on getting user details>> + "/photos?access_token=" + <<user accessToken>>,
        type:"POST",
        data:fd,
        processData:false,
        contentType:false,
        cache:false,
        success:function(data){
            console.log("success " + data);
        },
        error:function(shr,status,data){
            console.log("error " + data + " Status " + shr.status);
        },
        complete:function(){
            console.log("Ajax Complete");
        }
   });

} catch(e) {
    console.log(e);
}

function dataURItoBlob(dataURI,mime) {
    // convert base64 to raw binary data held in a string
    // doesn't handle URLEncoded DataURIs

    var byteString = window.atob(dataURI);

    // separate out the mime component


    // write the bytes of the string to an ArrayBuffer
    //var ab = new ArrayBuffer(byteString.length);
    var ia = new Uint8Array(byteString.length);
    for (var i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
    }

    // write the ArrayBuffer to a blob, and you're done
    var blob = new Blob([ia], { type: mime });

    return blob;
}

//EDIT AJAX SYNTAX

Ответ 3

Dan Answer работает лучше всего. Что-то еще, что может быть полезно в этом сценарии, является необязательным аргументом для публикации фотографий: "no_story". Этот аргумент по умолчанию имеет значение true, заставляющее фото-сообщение пропускать пользовательскую стенку. Добавив

fd.append("no_story", false);

вы можете обновить стену пользователя фотографической записью.

Я бы просто оставил это как комментарий, но... 50 Rep для комментариев.

Ответ 4

Я сделал что-то очень похожее на ваш вопрос. У меня был снимок веб-камеры, который должен был быть отправлен на страницу фан-сайта Facebook. Установка была в ресторане, где люди могли сфотографировать, и он будет опубликован на странице "Рестораны". Затем люди увидели бы QR-код к опубликованной facebook-фотографии, которую они могли бы выбрать для совместного использования в своем профиле. Надеюсь, это может помочь кому-то, потому что я много искал, чтобы добраться до этого рабочего РЕШЕНИЯ.

Примечание. Мое изображение уже закодировано BASE64.

//imageData is a base64 encoded JPG
function postSocial(imageData, message){       
        var ia = toUInt8Array(imageData);
        postImageToFacebook(mAccessTokenPage, "imageName", "image/jpeg",ia, message);
}

function toUInt8Array(dataURI) {
        // convert base64 to raw binary data held in a string
        // doesn't handle URLEncoded DataURIs
        var byteString = window.atob(dataURI);

        // write the bytes of the string to an ArrayBuffer
        //var ab = new ArrayBuffer(byteString.length);
        var ia = new Uint8Array(byteString.length);
        for (var i = 0; i < byteString.length; i++) {
            ia[i] = byteString.charCodeAt(i);
        }
        return ia;
    }

function postImageToFacebook( 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/ + {PAGE_ID} + "/photos?access_token=" + authToken, true );
        xhr.onload = function() {
            // ... Fill in your own
            //Image was posted 
           console.log(xhr.responseText);
        };
        xhr.onerror = function(){
            console.log("Error while sending the image to Facebook");
        };
        xhr.setRequestHeader( "Content-Type", "multipart/form-data; boundary=" + boundary );
        xhr.sendAsBinary( formData );
    }

Ответ 5

Вот как я смог опубликовать изображение в facebook, используя API-интерфейс facebook JS. Я использую функциональность HTML5 canvas. Он не полностью поддерживается каждым браузером.

Вам нужно сначала получить данные изображения. Затем инкапсулировать его в данные формы. Затем я использую API FB.login, чтобы получить токен доступа и идентификатор пользователя.

          var data = $('#map >> canvas').toDataURL('image/png');
          var blob;
          try {
            var byteString = atob(data.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);
            }
            blob = new Blob([ab], {type: 'image/png'});
          } catch (e) {
            console.log(e);
          }
          var fd = new FormData();
          fd.append("source", blob);
          fd.append("message", "Photo Text");
          FB.login(function(){
            var auth = FB.getAuthResponse();
            $.ajax({
              url:"https://graph.facebook.com/"+auth.userID+"/photos?access_token=" + auth.accessToken,
              type:"POST",
              data:fd,
              processData:false,
              contentType:false,
              cache:false,
              success:function(data){
                console.log("success " + data);
              },
              error:function(shr,status,data){
                console.log("error " + data + " Status " + shr.status);
              },
              complete:function(){
                console.log("Ajax Complete");
              }
            });
          }, {scope: 'publish_actions'});

Ответ 6

Мы можем упростить перекодировку изображений с использованием современного API Fetch вместо Uint8Array.

 var url = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="

 fetch(url)
  .then(res => res.blob())
  .then(blob => console.log(blob))`