Posting multiple Photos to one post

1.7k Views Asked by At

I have been trying to create an application which needs multiple photos to be attached to one post. These are the following attempts i tried,

First i used facebook-node-sdk which JS SDK to achieve different functionality, but Official Js Sdk does't have option for file to upload, when then i moved to attaching/inserting photo itself to HTTP POST with the help of form-data, with the following code-

    var form = new FormData();
    form.append('file', fs.createReadStream(picPaths[0]));
    form.append('message', "Hello"); //Put message
    var ACCESS_TOKEN = "ACCESS_TOKEN";
    var options = {
        method: 'post',
        host: 'graph.facebook.com',
        path:  '{Object-ID}/photos' + '?access_token=' + ACCESS_TOKEN,
        headers: form.getHeaders(),
    }

    var request = https.request(options, function(res) {
        console.log(res, false, null);
    });

    form.pipe(request);

    request.on('error', function(error) {
        console.log(error);
    });

This works with one photo.

But as you can see in this github.com/Thuzi/facebook-node-sdk/issues/113 which i started, it is not possible to attach more than one photo.

So as mentioned by dantman i stated looking in batch process, which can be found developers.facebook.com/docs/graph-api/making-multiple-requests titled under Uploading binary data. The one thing that hits and give me hope is this one statement.

The attached_files property can take a comma separated list of attachment names in its value.

Note That (batching with photos) also is not possible with this library or JS SDK (Please correct me if i am wrong)

You can do post images with curl like this,

curl -F 'access_token=ACCESS_TOKEN' -F 'batch=[{"method":"POST","relative_url":"{Object-Id}/photos","body":"message=Test Post","attached_files":"file1"}]' -F 'file1=@image1' -F 'file2=@image2' https://graph.facebook.com

The above code posts with one image

So my question is this, it possible to attach multiple images/binary_files to the post with the help of curl, something like ..."attached_files":"file1,file2"... as suggested by docs, please help me with this problem and if you have already done this can you please post the snapshot of your code.

Thanks, Ravi

2

There are 2 best solutions below

0
On

I finally figured out how.

So first, read the section here titled "Publishing a multi-photo post with uploaded photos": https://developers.facebook.com/docs/graph-api/reference/page/photos/#Creating

What it says is basically correct, however, it is not in JavaScript. Also, they don't emphasize enough an important step: You have to set "published" to "false" for the image you upload, for it to then be attachable to the post that gets created.

So anyway, here is the working code -- in JavaScript, and with "published" correctly set to false:

async function PostImageToFacebook(token, filename, mimeType, imageDataBlob, message) {
    var fd = new FormData();
    fd.append("access_token", token);
    fd.append("source", imageDataBlob);
    //fd.append("message", "photo message for " + filename);
    fd.append("no_story", "true");
    //fd.append("privacy", "SELF");
    fd.append("published", "false");

    // Upload image to facebook without story(post to feed)
    let uploadPhotoResponse = await $.ajax({
         url: "https://graph.facebook.com/me/photos?access_token=" + token,
         type: "POST",
         data: fd,
         processData: false,
         contentType: false,
         cache: false
    });
    console.log(`Uploaded photo "${filename}": `, uploadPhotoResponse);

    let uploadPhotoResponse2 = await $.ajax({
        url: "https://graph.facebook.com/me/photos?access_token=" + token,
        type: "POST",
        data: fd,
        processData: false,
        contentType: false,
        cache: false
  });
  console.log(`Uploaded photo "${filename}": `, uploadPhotoResponse2);

    let makePostResponse = await $.ajax({
        "async": true,
        "crossDomain": true,
        "url": "https://graph.facebook.com/v2.11/me/feed",
        "method": "POST",
        "headers": {
            "cache-control": "no-cache",
            "content-type": "application/x-www-form-urlencoded"
        },
        "data": {
            "message": "Testing multi-photo post2!",
            "attached_media[0]": `{"media_fbid":${uploadPhotoResponse.id}}`,
            "attached_media[1]": `{"media_fbid":${uploadPhotoResponse2.id}}`,
            "access_token": token
        }
    });
    console.log(`Made post: `, makePostResponse);
}

The code above currently just uploads the same image twice, then attaches both to the new post. Obviously, in real world usage you would replace the data in the second photo-upload with a different image.

Anyway, to use the function, just call it like so:

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

let imageDataURI = GetImageDataURIFromSomewhere();
let imageBlob = dataURItoBlob(imageDataURI);

PostImageToFacebook(fbToken, "some_filename", "image/png", imageBlob, window.location.href);
0
On

this is possible.

Note: This one is not an efficient way to do this but just for explaining purpose i am doing here,

The first hint that i got that it may be possible is from this post

Steps that i used:

  1. Follow the doc to create custom open graph stories
  2. Let's suppose you four image to attach (pic[1, 2, 3, 4])
  3. First i staged them with the help of new facebook-node-sdk v1.1.0-alpha1 with the code something like this (with batch process).

    FB.api( "", "post", {
        batch: [
        {
            method: "POST",
            relative_url: "me/staging_resources",
            attached_files: "file1",
            type:"image/png"
        }, {
            method: "POST",
            relative_url: "me/staging_resources",
            attached_files: "file2",
            type:"image/png"
        }, {
            method: "POST",
            relative_url: "me/staging_resources",
            attached_files: "file3",
            type:"image/png"
        }, {
            method: "POST",
            relative_url: "me/staging_resources",
            attached_files: "file4",
            type:"image/png"
        }],
        file1: fs.createReadStream(picPaths[0]),
        file2: fs.createReadStream(picPaths[1]),
        file3: fs.createReadStream(picPaths[2]),
        file4: fs.createReadStream(picPaths[3])
    },
    function(response) {
        console.log(response);
    });
    
  4. Now from the response part get the url and dis the post with the same library. With the code something like this.

    FB.api(
        "me/objects/{app-namespace}:{custom-object}",
        "post", {
            "object": {
                "og:title": "Sample Post",
                "og:image[0]": {
                    "url": "fbstaging:{...}",
                    "user_generated": true
                },
                "og:image[1]": {
                    "url": "fbstaging:{...}",
                    "user_generated": true
                },
                "og:image[2]": {
                    "url": "fbstaging:{...}",
                    "user_generated": true
                },
                "og:image[3]": {
                    "url": "fbstaging:{...}",
                    "user_generated": true
                }
            }
        },
        function(response) {
            console.log(response);
        }
    );
    

Now, with these two piece of code you will be able to push multiple images/photo to the single post.

Note: this can make more sense or can be done with the help of named batch process which is being described here.

Thanks, Ravi