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
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);
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:
Follow the doc to create custom open graph stories
Let's suppose you four image to attach (pic[1, 2, 3, 4])
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);
});
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
Related
I'm developing an electron app which must call an api to replace (update) file X in server by file Y which is in my computer.
The user download file X from Server in order to edit it, (this file will be named file Y in my computer).
When the user finish to edit file Y, i check if both files X and Y are differents and i call the api in order to replace file X by file Y. I don't need to put file Y in a form before calling api, i want to do it without form.
Only my request payload is different from what i expect to have, there is no problem in my request headers
I expect to have something like that
and i get this
Here is what i do
const fs = require('fs');
let fileY = fs.readFileSync(path.resolve('gitignore.txt'));
let form = new FormData();
form.append("type", "jur_document");
form.append("file", fileY, 'gitignore.txt');
form.append("saveActionType", "SAVEMAJOR");
form.append("attributes", "MIMETYPE=text/plain");
let settings = {
"async": true,
"url": `${Constante.URL}/documents`,
"method": "POST",
"type": "POST",
"headers": {
// "Content-Type": "text/plain",
"Authorization": sessionStorage.getItem('authorization')
},
"processData": false,
"contentType": false,
"mimeType": "multipart/form-data",
"data": form
};
$.ajax(settings)
.done((response) => {
console.log(response);
}).fail(err => {
console.log(err);
});
}
i finally get the solution
I read my file and create a blob which i use to recreate my file
const fs = require('fs');
let buffer = fs.readFileSync(`${app.getAppPath()}/test.txt`);
let fileY = new File([new Uint8Array(buffer)], 'test.txt', {
type: 'text/plain'
});
form.append("file", fileY);
and here is ajax settings
let settings = {
"url": `${Constante.URL}/documents`,
"type": "POST",
"headers": {
"Authorization": sessionStorage.getItem('authorization')
},
"processData": false,
"contentType": false,
"data": form
};
I'm using the Facebook Javascript SDK in my react app and I want to make a post with multiple photos. I know that that means I have to first post the pictures unpublished and then use the returned ids to make the post.
However, I'm having trouble finding good documentation and running into issues figuring out how to allow a user select and post a local picture (not from a url). The code is a bit difficult to put all here, but here are the steps I'm taking and the errors I'm getting:
Get file the user selected using a file input.
Encode the picture as a blob and put that and the access token into FormData to use in the api request.
var reader = new FileReader();
reader.onload = function(e) {
var arrayBuffer = e.target.result;
var blob = new Blob([arrayBuffer], { type: photo.type });
var pictureData = new FormData();
pictureData.append('access_token:', this.state.FBaccessToken);
pictureData.append('source', blob);
return pictureData;
}.bind(this)
return reader.readAsArrayBuffer(photo);
Do a post request
var encodedRequest = this.encodePhoto(photo);
FB.api(
"/me/photos?published=false",
"POST",
encodedRequest,
function (response) {
if (response && !response.error) {
//once successfully gotten the photos add them to the array of photo ids
temp.push({"media_fbid": response.id});
console.log(response);
}
else {
alert(response.error.message);
}
}.bind(this)
);
The error when I run it this way is that it doesn't seem to recognize the access token, but when I remove the access token from pictureData in step 2, and change the api encodedRequest part to this:
{
access_token: this.state.FBaccessToken,
source: encodedRequest,
},
I get the error "(#324) Requires upload file". I tried adding fileUpload: true, to the SDK init code but that also didn't seem to do anything. Posting simple text only statuses and reading from feed is all working fine.
Sorry for the long post, but I'd be really grateful if anyone has any insight! Thanks.
Is it the extra colon you have after access_token in your first pictureData.append() call?
pictureData.append('access_token:', this.state.FBaccessToken);
versus
pictureData.append('access_token', this.state.FBaccessToken);
Edit: Below is output from postman to post images referencing a file on my laptop
var form = new FormData();
form.append("source", "/Users/patricklambe/images/test.jpg");
form.append("access_token", "PAGEACCESSTOKEN");
form.append("caption", "check this photo");
var settings = {
"async": true,
"crossDomain": true,
"url": "https://graph.facebook.com/v2.11/444873272561515/photos",
"method": "POST",
"headers": {
"cache-control": "no-cache",
"postman-token": "1d786fec-c9b1-2494-1b5c-8fd0e2ea5ade"
},
"processData": false,
"contentType": false,
"mimeType": "multipart/form-data",
"data": form
}
$.ajax(settings).done(function (response) {
console.log(response);
});
Is there anybody that knows how to post events to an SharePoint Online Calender list using Sharepoint REST _api.
I found this post here on stack: link
But it uses authorization which I don’t have to use in my case because my app lives inside of sharepoint. I have found docs on how to make CRUD to a outlook calender. But it doesn’t cover sharepoint of course.
This is the code so far:
function PostToBokningar() {
var url = `${_spPageContextInfo.webAbsoluteUrl}/_api/web/lists/getbytitle('Bokningar')/items`;
//requestHeaders
var requestHeaders = {
"accept": "application/json;odata=verbose",
"content-type": "application/json;odata=verbose",
"X-RequestDigest": jQuery('#__REQUESTDIGEST').val()
}
//Data
var data = {
__metadata: { "type": "SP.Data.BokningarListItem" },
Title: "Test title",
EventDate: moment.utc("2017-12-12 10:00").format('YYYY-MM-DD HH:mm:ssZ'),
EndTime: moment.utc("2017-12-12 17:00").format('YYYY-MM-DD HH:mm:ssZ'),
Description: "test description"
};
//requestBod
var requestBody = JSON.stringify(data);
//Post
var post = jQuery.ajax({
url: url,
type: "POST",
headers: requestHeaders,
data: data
})
}
The error message I get is:
{"error":{"code":"-1, Microsoft.SharePoint.Client.InvalidClientQueryException","message":{"lang":"en-US","value":"Invalid JSON. A token was not recognized in the JSON content."}}}
Any suggestions?
Yes, you have two errors in your code. You are not sending the stringified json to the REST service. Replace the call to:
var post = jQuery.ajax({
url: url,
type: "POST",
headers: requestHeaders,
data: requestBody
})
And also, the field for the end of the event is called EndDate and not EndTime, so replace to:
var data = {
__metadata: { "type": "SP.Data.BokningarListItem" },
Title: "Test title",
EventDate: moment.utc("2017-12-12 10:00").format('YYYY-MM-DD HH:mm:ssZ'),
EndDate: moment.utc("2017-12-12 17:00").format('YYYY-MM-DD HH:mm:ssZ'),
Description: "test description"
};
I have created a form with textboxes and a dropdown menu, inside my code I've created a script which will be called when clicking "Send Form"
Lets say my field are : firstName, lastName, country (dropdown)
Here is the script:
function f1() {
var settings = {
"async": true,
"url": "https://api.TheSite.com/v2/applications/123456789/newJson.json",
"method": "POST",
"headers": {
"x-api-key": "123456789123456",
"content-type": "application/json",
},
"processData": false,
"data": "{\r\n \"deployment\": {\r\n \"revision\": \"string\",\r\n \"changelog\": \"string\",\r\n \"description\": \"string\",\r\n \"user\": \"string\"\r\n }\r\n}"
}
$.ajax(settings).done(function(response) {
console.log(response);
alert("The Form Was Sent");
});
}
I would like to insert those 3 variables' values inside the "data" string like so:
"data": "{\r\n \"deployment\": {\r\n \"revision\": \`firstName
\",\r\n \"changelog\": \"`lastName
and so on...
In the dropdown menu, I assume it will be displayed as an array. How do I include my variable inside?
First create an empty object and insert the data into it.
Next use JSON.strigify() to convert that into a JSON blob before you send it over to the server.
var data = {};
data.deployment = {};
data.deployment.revision = firstName;
data.deployment.changelog = lastName;
var settings = {
....,
data: JSON.stringify(data)
};
Since you are already using jQuery to perform your AJAX request, you should be aware that you can actually pass a native JavaScript object into the data portion of the request. You don't need to have it converted to a JSON string. If you want to, you can just stringify it.
You can actually establish default request options and then merge them with the data you want to request.
var defaults = {
url: 'https://api.TheSite.com/v2/applications/123456789/newJson.json',
method: 'POST',
contentType: 'application/json',
headers: {
'x-api-key': '123456789123456',
},
processData: false,
async: true
};
function makeXhrRequest(config) {
var xhrRequest = $.extend(true, defaults, config);
// If you want to convert the request to a json String.
//xhrRequest.data = JSON.stringify(data);
$.ajax(xhrRequest).done(function(data, textStatus, jqXHR) {
console.log(data);
alert("The Form was sent...");
});
}
var $myForm = $('form[name="my-form"]');
makeXhrRequest({
data : {
deployment : {
revision : $myForm.find('input[name="firstname"]').val(),
changelog : $myForm.find('input[name="lastname"]').val(),
description : 'string',
user : 'string'
}
}
});
SOLVED
this is the syntax that worked for me +$("#firstName")[0].value+ and this is the code :
"data":"{\r\n\deployment\: {\r\n revision\:"+"\""+$("#firstName")[0].value+"\","+"\r\n"
I am trying to post a .json file as a single document to an ArangoDB collection, from within javascript/ajax.
I can post (to ArangoDB) the .json file using curl, so that works
I can post (to ArangoDB) simple {key: value} pairs using AJAX, so that works, but combining the two seems to be a bridge too far. I have spent a couple of nights trying to get this far, so any help would be hugely appreciated. thanks in advance.
My javascript code looks like this
var database_URL = prompt("Please enter your URL", "http://xxx..xxx.xxxx.:8529/_db/collection_name/_api/document?collection=PA_Users&createCollection=false");
var fd = new FormData();
var selectedFile = document.getElementById('files').files[0];
console.log(selectedFile.name);// this works
fd.append(selectedFile.name,selectedFile);
var settings = {
url : database_URL,
type : "POST",
headers: {
'Authorization': "Basic " + btoa(username1 + ":" + passwrd1)
},
data: fd,
processData: false,
success: function(data) {
// display feedback to user
alert("booyah");
},
error: function(data) {
// display feedback to user
alert("boo hoo");
}
};
$.ajax(settings);
I think you should use /_api/import instead of /_api/document:
HTTP Interface for Bulk Imports
Here is a small working example (without authorization):
$.ajax({
type: "POST",
url:
'/_api/import?type=auto&collection=' +
encodeURIComponent(yourCollectionID) +
'&createCollection=false',
data: file,
processData: false,
contentType: 'json',
dataType: 'json',
complete: function(xhr) {
if (xhr.readyState === 4 && xhr.status === 201) {
callback(false);
} else {
try {
var data = JSON.parse(xhr.responseText);
if (data.errors > 0) {
// error
}
else {
// success
}
}
catch (err) {
console.log(err);
}
}
}
});
}
The api supports a few input formats:
1.) Single document
{name: "Jonny"}
2.) Multiple documents (one doc in each row)
{name: "Jonny"}
{name: "Adam"}
{name: "Peter"}
3.) Multiple documents in JSON array
[{name: "Jonny"}, {name: "Adam"}, {name: "Peter"}]