I have a video file on s3 that I want to post to a user Facebook account:
https.get(signedUrlOfObjectInS3, function(httpRes){
var form = new formData(); // that's form-data module https://github.com/felixge/node-form-data
form.append('source', httpRes);
var options = {
method: 'post',
host: 'graph-video.facebook.com',
path: '/me/videos?access_token=' + user_access_token,
headers: form.getHeaders(),
}
var buffer = '';
var apiCall = https.request(options, function (res){
res.on('data',function(chunk){
buffer += chunk;
});
res.on('end',function(){
var data = JSON.parse(buffer);
console.log('data from fb is: ' + util.inspect(data));
});
});
form.pipe(apiCall);
});
The response I get from Facebook is:
(#352) Sorry, the video file you selected is in a format that we don\'t support.
The video file on s3 is a mov file with a content type of video/quicktime.
OK, so apparently Facebook ignores the content type in the headers and guesses it from the file name. Since the s3 signed url doesn't end with filename.mov for example, it doesn't get it...
All I had to do was concating a '&f=filename.mov' to the end of the signedUrl, and now Facebook get that...
The following code actually worked fine for me for me:
https.get(signedUrlOfObjectInS3, function(httpRes) {
var form = new FormData(); // that's form-data module https://github.com/felixge/node-form-data
form.append('source', httpRes);
var options = {
method: 'post',
host: 'graph-video.facebook.com',
path: '/me/videos?access_token=' + user_access_token,
headers: form.getHeaders(),
}
var apiCall = https.request(options);
form.pipe(apiCall);
apiCall.on('response', function(res) {
console.log(res.statusCode);
});
});
try making the small difference in apiCall postback ,
other explanation might be that i've used a public amazon URL...
Related
I have an API POST endpoint that expects multipart file data. I need to invoke this endpoint whenever a file is uploaded to an S3 bucket.
Using the below piece of code, I get the content of the file as Buffer in the filedata.Body object.
const filedata = await s3.getObject(params).promise();
console.log('CONTENT:', filedata.Body);
As mentioned above, I need to send this content to the POST endpoint as formdata. I am using the following code for it, but it doesn't seem to work.
const FormData = require('form-data');
const post_body = new FormData();
post_body.append('file', filedata.Body.toString('utf-8')); // also tried sending buffer directly
const options = {
hostname: 'xxxxxamazonaws.com',
port: 80,
path: 'xxxxx',
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data'
}
};
const req = http.request(options, res => {
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
// some ode
});
});
req.on('error', (e) => {
console.error(e);
});
req.write(post_body);
req.end();
The above code errors out by saying that An instance of form data was received where a string or Uint8Array was expected.
I have also tried :
req.write(filedata.Body.toString('utf-8'));
This doesn't seem to work either. I am really stuck at this currently.
How can I call my API that expects a multipart file using the content received from S3?
I need to add an file attachment to a soap request from node.js application.
I am able to send request with node-soap library, and now I need to add a file to the request.
I did it with a java client or with soapUI, but I have to do it in node.js, maybe it's possible to do that overriding default request object ?
I didn't find a solution with node-soap, I had to build manually my soap request :
var soapHeader = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Header/><soapenv:Body><ws:method>';
var soapFooter = '</ws:method></soapenv:Body></soapenv:Envelope>';
function sendSoapRequestWithAttachments(soap,files){
var soapRequest = jsonToXml.buildObject(mail);
var finalSoapRequest = soapHeader + soapRequest + soapFooter;
var multipartMail = [];
// Add soap request
multipartMail.push({
'Content-Type': 'text/xml; charset=utf-8',
body: finalSoapRequest
});
// Add attachments
if (files) {
files.forEach(function (file) {
multipartMail.push({
'Content-Id': '<' + file.uuid + '>',
'Content-Type': 'application/octet-stream',
'Content-Transfer-Encoding': 'binary',
body: fs.createReadStream(file.path)
});
});
}
var options = {
uri: URL,
method: 'POST',
multipart: multipartMail
};
request.post(options, function (error, response) {
...
}
}
I found a way to send attachment using node-soap using base64 encoding
here is an example
import soap from 'soap'
import fs from 'fs'
async function main(){
const filepath = '/path/to/attachment/file.extension'
const client = await soap.createClientAsync(/* ... */)
const result = await client.AnApiMethodAsync({
expectedKeyForTheFile: await fs.readFileAsync(filepath, 'base64')
})
}
main()
I am using using AWS SES to post an email from an s3 bucket to a method on my server. I have an SES rule set that writes said email to the bucket (which works), then there is a lambda function which posts to a function on my server.
Here is the lambda function I am using (minus a few pieces of information).
var AWS = require('aws-sdk');
var https = require('https');
var s3 = new AWS.S3();
var queryString = require('querystring');
var bucketName = '<My-Bucket-Name>';
exports.handler = function (event, context) {
var sendToServer = function(emaildata) {
// Options and headers for the HTTP request
var dataString = queryString.stringify(emaildata);
var options = {
host: '<My-Host-Name>',
port: 443,
path: '<My-PATH>',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(dataString),
}
};
// Setup the HTTP request
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
var req = https.request(options, function (res) {
res.setEncoding('utf-8');
// Collect response data as it comes back.
var responseString = '';
res.on('data', function (data) {
responseString += data;
});
// Log the responce received from Twilio.
// Or could use JSON.parse(responseString) here to get at individual properties.
res.on('end', function () {
console.log('Response: ' + responseString);
context.succeed();
});
});
// Handler for HTTP request errors.
req.on('error', function (e) {
console.error('HTTP error: ' + e.message);
context.fail();
});
// Send the HTTP request to the Twilio API.
// Log the message we are sending to Twilio.
console.log('Start API call');
req.write(dataString);
req.end();
}
var sesNotification = event.Records[0].ses;
// Retrieve the email from your bucket
console.log("sesNotification = " + event.Records);
console.log("Key value = " + sesNotification.mail.messageId);
s3.getObject({
Bucket: bucketName,
Key: sesNotification.mail.messageId
}, function (err, data) {
if (err) {
console.log(err, err.stack);
context.fail();
} else {
console.log("Raw email:\n" + data.Body);
sendToServer(data);
}
});
};
The php script I am posting to has the the following code:
$this->layout=false;
$obj = json_encode($this->request->data);
I then email $obj to my personal email.
The message I get is:
{"AcceptRanges":"bytes","LastModified":"Wed, 02 Dec 2015 19:55:09 GMT","ContentLength":"2797","ETag":"\"1ee74034ec791514fa57d1ff13452737\"","ContentType":"application\/octet-stream","Metadata":"","Body":""}
What I am looking for is all the information pertaining to the email so I can do some fancy stuff on my server. What am I doing wrong? Any suggestions will be appreciated. Thanks.
The problem seems to be in your S3 callback function. data.Body isn't actually simple object that can be serialized. You have to stream it to a buffer, file, or turn it into a string (which I think is being done in your log statement).
http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getObject-property
Before your sendToServer call, try:
data.StringBody = data.Body.toString()
I have used the Winston module to create a daily log file for my offline app. I now need to be able to send or upload that file to a remote server via POST (that part already exists)
I know I need to write the file in chunks so it doesn't hog the memory so I'm using fs.createReadStream however I seem to only get a 503 response, even if sending just sample text.
EDIT
I worked out that the receiver was expecting the data to be named 'data'. I have removed the createReadSteam as I could only get it to work with 'application/x-www-form-urlencoded' and a synchronous fs.readFileSync. If I change this to 'multipart/form-data' on the php server would I be able to use createReadStream again, or is that only if I change to physically uploading the json file.
I've only been learning node for the past couple of weeks so any pointers would be gratefully received.
var http = require('http'),
fs = require('fs');
var post_options = {
host: 'logger.mysite.co.uk',
path: '/',
port: 80,
timeout: 120000,
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}
var sender = http.request(post_options, function(res) {
if (res.statusCode < 399) {
var text = ""
res.on('data', function(chunk) {
text += chunk
})
res.on('end', function(data) {
console.log(text)
})
} else {
console.log("ERROR", res.statusCode)
}
})
var POST_DATA = 'data={['
POST_DATA += fs.readFileSync('./path/file.log').toString().replace(/\,+$/,'')
POST_DATA += ']}'
console.log(POST_DATA)
sender.write(POST_DATA)
sender.end()
After gazillion of trial-failure this worked for me. Using FormData with node-fetch. Oh, and request deprecated two days ago, btw.
const FormData = require('form-data');
const fetch = require('node-fetch');
function uploadImage(imageBuffer) {
const form = new FormData();
form.append('file', imageBuffer, {
contentType: 'image/jpeg',
filename: 'dummy.jpg',
});
return fetch(`myserver.cz/upload`, { method: 'POST', body: form })
};
In place of imageBuffer there can be numerous things. I had a buffer containing the image, but you can also pass the result of fs.createReadStream('/foo/bar.jpg') to upload a file from drive.
copied from https://github.com/mikeal/request#forms
var r = request.post('http://service.com/upload', function optionalCallback (err, httpResponse, body) {
if (err) {
return console.error('upload failed:', err);
}
console.log('Upload successful! Server responded with:', body);
})
var form = r.form()
form.append('my_field1', 'my_value23_321')
form.append('my_field2', '123123sdas')
form.append('my_file', fs.createReadStream(path.join(__dirname, 'doodle.png')))
Have a look at the request module.
It will provide you the ability to stream a file to POST requests.
I am trying to integrate twilio with Node.js+express.
I don't have a site yet. what value should I give for HOSTNAME, along with SID and AUTH_TOKEN, these values I got from twilio site.
I have written some code, whatever suggestion given below I have placed in to views folder in twiclient.js , I have added a route in app.js to redirect the request if /twi is called , but I am not getting any result. some errors are appearing in the console, would you please help me figure out what I'm doing wrong? I have placed the correct SID, token and hostname, as specified below.
app.js has the following entry, does anything else need to be done for the twilio calling part to work?
Also, where should I define the GUI for calling a phone in the views folder?
var TwilioClient = require('twilio').Client,
Twiml = require('twilio').Twiml,
sys = require('sys');
var client = new TwilioClient('MY_ACCOUNT_SID', 'MY_AUTH_TOKEN', 'MY_HOSTNAME');
var phone = client.getPhoneNumber('+2323232323');
phone.setup(function() { phone.makeCall('+15555555555', null, function(call) {});
phone.setup(function() {
phone.makeCall('+15555555555', null, function(call) {
call.on('answered', function(callParams, response) {
response.append(new Twiml.Say('Hey buddy. Let\'s meet for drinks later tonight.'));
response.send();
});
});
});
The hostname is 'api.twilio.com'. Your SID and AUTH_TOKEN come from your twilio account. When you log in, go to the dashboard. You'll find your SID and AUTH_TOKEN listed there.
Here's the code I use to make a request to twilio to place a call. It should help you get started.
var https = require('https');
var qs = require('querystring');
var api = 'your api key';
var auth = 'your auth token';
var postdata = qs.stringify({
'From' : '+5554321212',
'To' : '+5552226262',
'Url' : 'http://yourwebsite.com/call'
});
var options = {
host: 'api.twilio.com',
path: '/2010-04-01/Accounts/<your api key>/Calls.xml',
port: 443,
method: 'POST',
headers: {
'Content-Type' : 'application/x-www-form-urlencoded',
'Content-Length' : postdata.length
},
auth: api + ':' + auth
};
var request = https.request(options, function(res){
res.setEncoding('utf8');
res.on('data', function(chunk){
console.log('Response: ' + chunk);
})
})
request.write(postdata);
request.end();