Posting Image Event on javascript facebook api - javascript

Ok I'm stuck, I want to create an event in facebook, using javascript facebook api, and I want to load an image on the event cover. I can not figure out how I can do it.
I create an image in a canvas and I can upload to facebook using an sendAsBinnary function
from: https://stackoverflow.com/a/5303242/945521
And this function
Facebook.prototype.postImageToFacebook = function(authToken, filename, mimeType, imageData, message){
try {
showMessage("Creating post...");
// this is the multipart/form-data boundary we'll use
var boundary = '----------RaNdOm_crAPP' + getBoundary();
// 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();
var xhr = null;
if (window.XDomainRequest) {
xhr = new XDomainRequest();
}
else if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
}
else {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
xhr.onload = function() {
window.alert("The photo was published successfully!!");
};
showMessage("Sending request...");
xhr.open("POST", "https://graph.facebook.com/me/photos?access_token=" + authToken, true);
if (xhr.setRequestHeader)
xhr.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
xhr.sendAsBinary(formData);
} catch (ex) {
stopWaitingSpin();
debugLog(ex);
}
};
and with this
FB.api("/me/events", "POST", {
"name": name,
"start_time": start_time,
//"end_time":end_time,
"description": description,
"location": location,
//"location_id":location_id,
"privacy_type": privacy_type
},
function(response) {
if (response && !response.error) {
var event_id = response.id;
console.log(response);
}
});
I can create a event.
But what need to call to send the image to the cover on event???
Thank's to all

Actually its nowhere mentioned in the documentation yet, but to publish a cover photo on an event you need to call \POST /{event-id} with param cover_url:
{event-id} could be obtained as a result when you created an event.
FB.api("/{event-id}", "POST", {
cover_url: {image-url}
},
function(response) {
console.log(response); // you'll get the response as 'true' or 'false'
});

Related

XHR POST request with multi files using FileReader API

This is my first question on StackOverflow :)
I'm learning Javascript for a personal project and I get some troubles with asynchronous functions. Something is not clear to me yet with such functions :( .
I try to upload multifiles in an HTML form to prepare an XHR request. Below is my function that I trigger with a an AddEventListener on the submit button.
I found explications on MDN learning web development but since it was only for one file I custom it with a for loop on formCell[5].files (declared as global constant) which is where my files are.
The problem seems to be with the asynchronous behavior. Is an expert on stack have advice to me ? Is there a solution with promises for example ? The "If" with SetTimeOut to wait for loop execution don't seem to me very pretty.
I think I tried hundred solutions without success :)
Thanks a lot in advance,
Regards,
Romain
function sendData() {
/* Loading files */
var binnaryFiles = [null];
for (let i = 0; i < formCell[5].files.length; i++) {
let reader = new FileReader(); // FileReader API
reader.addEventListener("load", function () { // Asynchronous function (return result when read)
binnaryFiles[i] = reader.result;
});
// Read the file
reader.readAsBinaryString(formCell[5].files[i]);
}
if(binnaryFiles.length !== formCell[5].files.length) {
setTimeout( sendData, 10 );
return;
}
console.log("final" + binnaryFiles.length);
const XHR = new XMLHttpRequest();
const boundary = "blob"; // We need a separator to define each part of the request
let msg = "";
/* Loading files in the request */
for (let i = 0; i < formCell[5].files.length; i++) {
msg += "--" + boundary + "\r\n";
msg += 'content-disposition: form-data; '
+ 'name="' + formCell[5].name + '"; '
+ 'filename="' + formCell[5].files[i].name + '"\r\n';
msg += 'Content-Type: ' + formCell[5].files[i].type + '\r\n';
msg += '\r\n';
msg += binnaryFiles[i] + '\r\n';
}
/* Loading texts in the request */
for (let i = 0; i < formCell.length - 1; i++) {
msg += "--" + boundary + "\r\n";
msg += 'content-disposition: form-data; name="' + formCell[i].name + '"\r\n';
msg += '\r\n';
msg += formCell[i].value + "\r\n";
}
msg += "--" + boundary + "--";
XHR.addEventListener("load", function(event) {
alert( 'Yeah! Data sent and response loaded.' );
});
XHR.addEventListener("error", function(event) {
alert("Oops! Something went wrong.");
} );
XHR.open("POST", "http://localhost:3000/upload");
XHR.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
XHR.send(msg);
console.log(msg);
}
I think I finished by solving my problem using Promises :)
If anyone could confirm me that the code below is correct it could help me :)
Thanks,
Romain
function fileUpLoad(fileToUpload) {
return new Promise((resolve, reject) => {
const reader = new FileReader(); // FileReader API
reader.addEventListener("load", function () { // Asynchronous function (return result when read)
resolve(reader.result);
reject(reader.error);
});
// Read the file
reader.readAsBinaryString(fileToUpload);
});
}
/* Sending message */
function sendData(filesUploaded) {
let binnaryFiles = filesUploaded;
const XHR = new XMLHttpRequest();
const boundary = "blob"; // We need a separator to define each part of the request
let msg = "";
/* Loading files in the request */
for (let i = 0; i < binnaryFiles.length; i++) {
msg += "--" + boundary + "\r\n";
msg += 'content-disposition: form-data; '
+ 'name="' + formCell[5].name + '"; '
+ 'filename="' + formCell[5].files[i].name + '"\r\n';
msg += 'Content-Type: ' + formCell[5].files[i].type + '\r\n';
msg += '\r\n';
msg += binnaryFiles[i] + '\r\n';
}
/* Loading texts in the request */
for (let i = 0; i < formCell.length - 1; i++) {
msg += "--" + boundary + "\r\n";
msg += 'content-disposition: form-data; name="' + formCell[i].name + '"\r\n';
msg += '\r\n';
msg += formCell[i].value + "\r\n";
}
msg += "--" + boundary + "--";
XHR.addEventListener("load", function(event) {
alert( 'Yeah! Data sent and response loaded.' );
});
XHR.addEventListener("error", function(event) {
alert("Oops! Something went wrong.");
} );
XHR.open("POST", "http://localhost:3000/upload");
XHR.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
XHR.send(msg);
console.log(msg);
}
/* Validation on submit calling */
form.addEventListener("submit", function (evt) {
evt.preventDefault();
if (validationOnSubmit()) {
if (formCell[5].files.length > 0) {
let fileUploadingPromise = []
for (let i = 0; i < formCell[5].files.length; i++) {
fileUploadingPromise[i] = fileUpLoad(formCell[5].files[i]);
}
let binnaryFiles = [null];
Promise.all(fileUploadingPromise)
.then (resolve => {
for (let i = 0; i < formCell[5].files.length; i++) {
binnaryFiles[i] = resolve[i];
}
sendData(binnaryFiles)
})
.catch (reject => {
console.log(reject);
});
} else {
sendData(0);
}
}
});

Where my mistake in converting jquery ajax to pure js ajax request

That's my JQuery code which is currently working ->
$("#newsLetter-form").on('submit',function(event){
event.preventDefault();
email = $('#emailId').val();
console.log(email);
$.ajax({
url: '/subscribes/emailSubscribe',
type:'POST',
data:{
"_token": "{{ csrf_token() }}",
email:email,
},
success:function(response){
console.log(response);
$('#responseFromSub').text("Registred!");
$('#responseFromSub').css('background','lightgreen')
$('#newsLetter-form').css('display','none');
$('.sucsessMessage').fadeIn(1);
setTimeout(function(){$('.sucsessMessage').fadeOut(1);$('#newsLetter-form').css('display','flex');},3000);
},
error:function(response){
console.log(response);
var val = 'asdasd:111122:123123123';
var response1 = response.responseJSON.message.substring(response.responseJSON.message.indexOf("\"title\":"));
response1 = response1.split(":").pop();
response1 = response1.split(',')[0];
response1 = response1.replace("\"", "");
response1 = response1.replace("\"", "");
console.log(response1);
$('#responseFromSub').text(response1);
$('#responseFromSub').css('background','red');
$('#newsLetter-form').css('display','none');
$('.sucsessMessage').fadeIn(1);
setTimeout(function(){$('.sucsessMessage').fadeOut(1);$('#newsLetter-form').css('display','flex');},3000);
},
});
});
And this is my converted code which isn't working, it says 400 bad request wrong data. I'm using laravel and mailchimp for newsletter with jquery everything is working but with this pure js code, no ->
function myFunc123() {
var email1 = document.getElementById("emailId").value;
alert(email1);
var data = {
"_token": '{{ csrf_token() }}',
email: email1
};
var boundary = String(Math.random()).slice(2);
var boundaryMiddle = '--' + boundary + '\r\n';
var boundaryLast = '--' + boundary + '--\r\n'
var body = ['\r\n'];
for (var key in data) {
body.push('Content-Disposition: form-data; name="' + key + '"\r\n\r\n' + data[key] + '\r\n');
}
body = body.join(boundaryMiddle) + boundaryLast;
var xhr = new XMLHttpRequest();
xhr.open('POST', '/subscribes/emailSubscribe', true);
xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary);
xhr.onreadystatechange = function () {
if (this.readyState != 4) return;
alert(this.responseText);
}
xhr.send(body);
}
I fixed it the problem was here ->
var email1 = document.getElementById("emailId").value;
alert(email1);
var data = {
"_token": '{{ csrf_token() }}',
email: email1
Now it's working..
BUT the page is refreshing after request how can I disable refreshing ?
You forgot event.preventDefault(), which was in the jQuery code. The default behaviour is to refresh the page on submit (which is a very dumb default), you want to prevent this.
Okay, final converted version looks like that.
var ele = document.getElementById("newsLetter-form");
ele.addEventListener("submit", handleEmail, false);
function handleEmail(event) {
event.preventDefault();
var email1 = document.getElementById("emailId").value;
var data = {
"_token": '{{ csrf_token() }}',
email: email1
};
var boundary = String(Math.random()).slice(2);
var boundaryMiddle = '--' + boundary + '\r\n';
var boundaryLast = '--' + boundary + '--\r\n'
var body = ['\r\n'];
for (var key in data) {
body.push('Content-Disposition: form-data; name="' + key + '"\r\n\r\n' + data[key] + '\r\n');
}
body = body.join(boundaryMiddle) + boundaryLast;
var xhr = new XMLHttpRequest();
xhr.open('POST', '/subscribes/emailSubscribe', true);
xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary);
xhr.onreadystatechange = function () {
if(xhr.status===200)
{
document.getElementById("responseFromSub").innerHTML="Registered";
document.getElementById("responseFromSub").style.background="lightgreen";
document.getElementById("newsLetter-form").style.display="none";
document.getElementsByClassName("sucsessMessage")[0].style.display="block";
setTimeout(function () {
document.getElementsByClassName("sucsessMessage")[0].style.display="none";
document.getElementById("newsLetter-form").style.display="flex";
}, 3000);
}
else
{
document.getElementById("responseFromSub").innerHTML="Something goes wrong..";
document.getElementById("responseFromSub").style.background="red";
document.getElementById("newsLetter-form").style.display="none";
document.getElementsByClassName("sucsessMessage")[0].style.display="block";
setTimeout(function () {
document.getElementsByClassName("sucsessMessage")[0].style.display="none";
document.getElementById("newsLetter-form").style.display="flex";
}, 3000);
}
}
xhr.send(body);
}

How to manually create multipart/form-data

We can use .formData() of Body mixin to return a FormData representation of data at Chromium (Chrome) 60+ and Firefox 39+
Relevant specifications:
7.2 The Multipart Content-Type
Returning Values from Forms: multipart/form-data
Errata
Clarification of Body package data algorithm with bytes, FormData and multipart/form-data MIME type #392
Documenting de-facto handling of multipart/form-data form field file uploads #3040
Related
Multipart HTTP response
How to upload files in Web Workers when FormData is not defined
How to manually create multipart/form-data using JavaScript at client and at server to serve the multipart/form-data as a response?
You can create multipart/form-data manually with XMLHttpRequest like this example.
function multiPost(method, url, formHash){
var boundary = "nVenJ7H4puv"
var body = ""
for(var key in formHash){
body += "--" + boundary
+ "\r\nContent-Disposition: form-data; name=" + formHash[key].name
+ "\r\nContent-type: " + formHash[key].type
+ "\r\n\r\n" + formHash[key].value + "\r\n"
}
body += "--" + boundary + "--\r\n"
var xml = new XMLHttpRequest();
xml.open(method, url)
xml.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + boundary)
xml.setRequestHeader("Content-Length", body.length)
xml.send(body)
}
You can write you own FormData polyfill, or just google it "FormData polyfill"))) And also you can use normal FormData at browsers Chrome, FireFox, Opera, Safari, IE(10+), Edge.
FormData polyfill is only useful for old IE, and for workers, but for workers you better should use this - https://gist.github.com/Rob--W/8b5adedd84c0d36aba64
wikipedia
standart formdata not of body
What you need to do? You want send formdata or recieve it at js?
You can try to use my polyfill, but I have not tested it.
sample:
var data = new RawFormData();
data.append("key","value")
data.append("key", new Blob("test"), "my file.txt");
data.getOutputDeferred().then(function(formData){
var xml = new XMLHttpRequest();
xml.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + data.getBoundry());
xml.setRequestHeader("Content-Length", formData.length);
xml.open(method, url);
xml.send(formData);
});
code:
/**
* #constructor
*/
RawFormData = function () {
this._promises = [];
this._boundry = this.makeBoundary();
};
/**
* #return {string}
*/
RawFormData.prototype.getBoundary = function () {
return this._boundry;
}
/**
* #return {string}
*/
RawFormData.prototype.makeBoundary = function () {
return 'MyBoundary' + window.btoa(Math.random().toString()).substr(0, 12);
};
/**
* #param {string} name
* #param {string|number|File|Blob|boolean|null|undefined} val
* #param {string=} filename
*/
RawFormData.prototype.append = function (name, val, filename) {
var prom = null;
if(val instanceof File || val instanceof Blob){
prom = this.readAsBinaryString(val).then(function(base64){
var contentType = val.type || 'application/octet-stream';
var result = '--' + this._boundry + '\r\n' +
'Content-Disposition: form-data; ' +
'name="' + name + '"; filename="' + this.encode_utf8(filename || "blob") + '"\r\n' +
'Content-Type: ' + contentType + '\r\n\r\n' +
base64 + '\r\n';
return result;
}.bind(this))
}else{
prom = new Promise(function(resolve){
return '--' + this._boundry + '\r\n' +
'Content-Disposition: form-data; ' +
'name="' + this.encode_utf8(name) + '"\r\n\r\n' +
this.encode_utf8(val) + '\r\n'
}.bind(this));
}
this._promises.push(prom);
return prom;
};
/**
* #return {File|Blob} blob
* #return {Promise<string>}
*/
RawFormData.prototype.readAsBinaryString = function (blob) {
var reader = new FileReader();
return new Promise(function(resolve,reject){
var binStringCallback = function (e) {
resolve(e.target.result);
};
var arrBufferCallback = function (e) {
var binary = "";
var bytes = new Uint8Array(e.target.result);
var length = bytes.byteLength;
for (var i = 0; i < length; i++) {
binary += String.fromCharCode(bytes[i]);
}
resolve(binary);
};
reader.onerror = reader.onabort = function () {
resolve(null);
};
if (typeof reader.readAsBinaryString != "undefined") {
reader.onload = binStringCallback;
reader.readAsBinaryString(blob);
} else {
reader.onload = arrBufferCallback;
reader.readAsArrayBuffer(blob);
}
});
};
RawFormData.prototype.encode_utf8 = function( s ){
return unescape( encodeURIComponent( s ) );
}
RawFormData.prototype.getOutputDeferred = function () {
return Promise.all(this._promises).then(function (rows) {
var output = '--' + this._boundry + '\r\n';
rows.forEach(function(row) {
output += row;
});
output += '--' + this._boundry + '\r\n';
return output;
}.bind(this));
};

How to use publish_action permission of facebook api?

I want to post base64 encoded images in facebook. Below is my code
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/me/photos?access_token=' + authToken, true);
xhr.onload = xhr.onerror = function () {
console.log(xhr.responseText);
};
xhr.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
if(!xhr.sendAsBinary){
xhr.sendAsBinary = function(datastr) {
function byteValue(x) {
return x.charCodeAt(0) & 0xff;
}
var ords = Array.prototype.map.call(datastr, byteValue);
var ui8a = new Uint8Array(ords);
this.send(ui8a.buffer);
}
}
xhr.sendAsBinary(formData);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
alert('Your image has been successfully shared');
}
}
};
var data = yourDesigner.getProductDataURL();
var encodedPng = data.substring(data.indexOf(',') + 1, data.length);
var decodedPng = Base64Binary.decode(encodedPng);
// var decodedPng = dataURItoBlob(test,"png");
FB.getLoginStatus(function (response) {
var request = {};
if (response.status === "connected") {
request = postImageToFacebook(response.authResponse.accessToken, "test", "image/png", decodedPng, "www.captivations.com.au");
} else if (response.status === "not_authorized") {
FB.login(function (response) {
request = postImageToFacebook(response.authResponse.accessToken, "test", "image/png", decodedPng, "www.captivations.com.au");
}, {scope: "publish_actions"});
} else {
FB.login(function (response) {
request = postImageToFacebook(response.authResponse.accessToken, "test", "image/png", decodedPng, "www.captivations.com.au");
}, {scope: "publish_actions"});
}
});
I can post images when i logged into my facebook account . But when i tried to post the images from other accounts i got following error
"error": {
"message": "(#200) Requires extended permission: publish_actions",
"type": "OAuthException",
"code": 200,
"fbtrace_id": "EAcb5VG/eFS"
}
I think its permission issue of the facbook api. Can you help me on managing "publish action" permission of facebook?
From https://developers.facebook.com/docs/facebook-login/permissions:
The "publish_actions" provides access to publish Posts, Open Graph actions, achievements, scores and other activity on behalf of a person using your app.
Your app does not need to request the publish_actions permission in order to use the Feed Dialog, the Requests Dialog or the Send Dialog.
If you use the "publish_actions" permission in another way you have to requests Facebook to review how your app uses the "publish_actions" permission.

Javascript: Upload image from Canvas to FB via Graph API

I am composing an image in a canvas, I get the base64 image data by using canvas.toDataURL('png') and trimming the additional information.
var dataUrl = canvas.toDataURL('png');
var escapedBase64Data = dataUrl.replace("data:image/png;base64,","");
After that I try to post to facebook using:
FB.api('/me/photos', 'post', { source:data});
Photos (https://developers.facebook.com/docs/reference/api/user/) has a source property. This is where you will place the data content (multipart/form-data) of your photo.
I convert my base64 encoded data to multipart/form-data by specifying the headers.
The result looks like this:
--0.2242348059080541
Content-Disposition: file; name="file"; filename="image.png"
Content-Type: image/png
Content-Transfer-Encoding: base64
iVBORw0KGgoAAAANSUhEUgAAAfQAAAH0CAYAAADL1t+KAAAbBElEQVR4Xu3dP4jre0LG4V2xsFVYEKy
...
QAAAABJRU5ErkJggg==
--0.2242348059080541--
After I complete the FB api call I receive the following error:
Object {message: "(#324) Requires upload file", type: "OAuthException", code: 324}
Any suggestions?
Thanks
Here a working code example :
var boundary = '----ThisIsTheBoundary1234567890';
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 += f.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.onload = xhr.onerror = function() {
// error managment
};
xhr.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
//Send the request
xhr.sendAsBinary(formData);
Here is an easy solution:
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/

Categories