node.js 上传 Base64 图片 Facebook Graph API

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16214300/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 14:18:50  来源:igfitidea点击:

Upload Base64 Image Facebook Graph API

javascriptnode.jsfacebook-graph-apiencodingbase64

提问by Mauro

I'm trying to upload a base64 image to a FaceBook page using Node.js. I have managed to get the upload working with all the multipart data etc should I read the file from the filesystem (ie. using fs.readFileSync('c:\a.jpg')

我正在尝试使用 Node.js 将 base64 图像上传到 Facebook 页面。如果我从文件系统读取文件(即使用 fs.readFileSync('c:\a.jpg')

However, should I use the base64 encoded image and try upload it, it give me the following error : {"error":{"message":"(#1) An unknown error occurred","type":"OAuthException","code":1}}

但是,如果我使用 base64 编码的图像并尝试上传它,它会给我以下错误: {"error":{"message":"(#1) An unknown error occurred","type":"OAuthException","code":1}}

I have tried converting it to binary by new Buffer(b64string, 'base64');and uploading that, but no luck.

我尝试将其转换为二进制文件new Buffer(b64string, 'base64');并上传,但没有运气。

I have been struggling with this for 3 days now, so anyhelp would be greatly appreciated.

我已经为此苦苦挣扎了 3 天,因此将不胜感激。

Edit : If anyone also knows how I could convert the base64 to binary and successfully upload it, that would also work for me.

编辑:如果有人也知道我如何将 base64 转换为二进制文件并成功上传它,那也对我有用。

Edit : Code Snippet

编辑:代码片段

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

采纳答案by Dan Brown

The code above didn't quite work for me (Missing comma after type:"POST",and data URI to blob function reported errors. I got the following code to work in Firefox and Chrome:

上面的代码对我来说不太适用(缺少逗号之后type:"POST",和 blob 函数的数据 URI 报告了错误。我得到了以下代码在 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' });
}

Here's the code at GitHub https://github.com/DanBrown180/html5-canvas-post-to-facebook-base64

这是 GitHub https://github.com/DanBrown180/html5-canvas-post-to-facebook-base64上的代码

回答by Brune

I hope this will be useful. By doing photo upload to FB only with the help of javascript you can use the following method. Required thing here are imageData(which is base64 format of image) and the mime type.

我希望这会很有用。通过仅在 javascript 的帮助下将照片上传到 FB,您可以使用以下方法。这里需要的是 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

//编辑AJAX语法

回答by Schenn

Dan's Answer works the best. Something else that might be helpful in this scenario is the optional argument for posting photos: 'no_story'. This arg defaults to true forcing the photo-post to skip the user's wall. By adding

丹的回答效果最好。在这种情况下可能有帮助的其他内容是发布照片的可选参数:'no_story'。此参数默认为 true,强制照片发布跳过用户的墙。通过添加

fd.append("no_story", false);

you can update the user's wall with the photo-post.

您可以使用照片贴更新用户的墙。

I would have just left this as a comment but... 50 Rep for comments.

我会留下这个作为评论但是... 50 代表评论。

回答by Max Prokopov

We can simplify image recoding by usage of the modern Fetch API instead of Uint8Array.

我们可以通过使用现代 Fetch API 而不是 Uint8Array 来简化图像重新编码。

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

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

回答by luschn

Here is an example that does not need jQuery or other libraries, just the native Fetch API:

这是一个不需要 jQuery 或其他库,只需要原生 Fetch API 的示例:

const dataURItoBlob = (dataURI) => {
    let byteString = atob(dataURI.split(',')[1]);
    let ab = new ArrayBuffer(byteString.length);
    let ia = new Uint8Array(ab);
    for (let i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
    }
    return new Blob([ia], {
        type: 'image/jpeg'
    });
}
const upload = async (response) => {
    let canvas = document.getElementById('canvas');
    let dataURL = canvas.toDataURL('image/jpeg', 1.0);
    let blob = dataURItoBlob(dataURL);
    let formData = new FormData();
    formData.append('access_token', response.authResponse.accessToken);
    formData.append('source', blob);

    let responseFB = await fetch(`https://graph.facebook.com/me/photos`, {
        body: formData,
        method: 'post'
    });
    responseFB = await responseFB.json();
    console.log(responseFB);
};
document.getElementById('upload').addEventListener('click', () => {
    FB.login((response) => {
        //TODO check if user is logged in and authorized publish_actions
        upload(response);
    }, {scope: 'publish_actions'})
})

Source: http://www.devils-heaven.com/facebook-javascript-sdk-photo-upload-from-canvas/

来源:http: //www.devils-heaven.com/facebook-javascript-sdk-photo-upload-from-canvas/

回答by tim

I did something very similar to your question. I had a webcam-snapshot that needed to be POSTed to a Facebook Fan Page. The setup was in a restaurant where people could take a picture and it would be posted onto the Restaurants Page. People would then see a QR code to the posted facebook-photo which they could choose to share on their own profile. Hope this can help somebody because I searched a lot to get to this working SOLUTION

我做了与你的问题非常相似的事情。我有一个需要发布到 Facebook 粉丝页面的网络摄像头快照。设置在一家餐厅,人们可以在那里拍照,然后将其发布到餐厅页面上。然后人们会看到张贴的 facebook 照片的二维码,他们可以选择在自己的个人资料上分享。希望这可以帮助某人,因为我搜索了很多以获得这个工作解决方案

Note:My image is BASE64 encoded already.

注意:我的图像已经是 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'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/ + {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 );
    }

回答by Alexandre Mélard

Here is how I was able to post an image to facebook using the facebook JS API. I am using the canvas HTML5 functionality. It's not fully supported by every browser.

这是我如何使用 facebook JS API 将图像发布到 facebook。我正在使用画布 HTML5 功能。并非每个浏览器都完全支持它。

You need first to get the image data. Then to encapsulate it in a form data. I then use the FB.login API in order to retrieve the access token and the userID.

您首先需要获取图像数据。然后把它封装在一个表单数据中。然后我使用 FB.login API 来检索访问令牌和用户 ID。

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