I am trying to upload an image file from my node.js application to a group's drive in Sharepoint.
As the official documentation states, I'm making my request as follows:
PUT /groups/{group-id}/drive/items/{parent-id}:/{filename}:/content
With the binary image in the body: "The contents of the request body should be the binary stream of the file to be uploaded."
The problem is that the image is uploaded but as a corrupted file. I tried different solutions and still don't see why is always the image corrupted.
Here is my code:
//i get my image from a URL first
https.get(url.parse(attachment.contentUrl), function (response) {
var data = [];
response.on('data', function (chunk) {
data.push(chunk);
});
response.on('end', function () {
if (response.statusCode === 200) {
var buffer = Buffer.concat(data);
//store my image in a local file to test if image is correct (which it is)
fs.writeFile(localFileName, buffer, (fsError) => {
//error handling
});
functions.uploadImageToSharepoint(session, localFileName, buffer,
function (err, body, res) {
if (err) {
console.error(err);
}else{
console.log('OK!');
}
});
} else {
//error handling
}
});
}).on('error', function (e) {
console.log("error2: " + e);
});
//and the request to graph api
function uploadImageToSharepoint(session, fileName, data, callback) {
var options = {
url: 'https://graph.microsoft.com/v1.0/groups/xxxxxxx/drive/root:/yyyyyy/fileName.jpg:/content',
method: 'PUT',
body: data,
json: true,
headers: {
'Content-Type': 'image/jpg',
Authorization: 'Bearer ' + session.userData.accessToken
}
};
request(options, function (err, res, body) {
if (err) return callback(err, body, res);
if (parseInt(res.statusCode / 100, 10) !== 2) {
if (body.error) {
return callback(new Error(res.statusCode + ': ' + (body.error.message || body.error)), body, res);
}
return callback(err, body, res);
}
callback(err, body ,res);
});
}
The file is most likely getting corrupted due to the following option for request:
var options = {
json: true, //<--setting this option sets body to JSON representation of value
//another properties are omitted for clarity
};
In that case request sets body to JSON representation of value and adds accept header to application/json for Upload endpoint and binary file get corrupted.
The solution would be to omit json option from a request and use the proper content-type only:
var options = {
url: '/me/drive/root:/filename.jpg:/content',
method: 'PUT',
body: data,
headers: {
'Content-Type': 'image/jpg',
Authorization: 'Bearer ' + accessToken
}
};
Related
At the moment I am using npm module request to upload file with application/octet-stream content type. The problem is that I cannot get response body back. It is happening due to a known bug: https://github.com/request/request/issues/3108
Can you provide me an alternate ways to upload file to an API with an application/octet-stream content type?
Have you tried loading the file to a buffer rather than a stream? I appreciate in many contexts a stream is preferable, but often just loading into memory is acceptable. I've used this approach with no issues:
const imageBuffer = fs.readFileSync(fileName); // Set filename here..
const options = {
uri: url, /* Set url here. */
body: imageBuffer,
headers: {
'Content-Type': 'application/octet-stream'
}
};
request.post(options, (error, response, body) => {
if (error) {
console.log('Error: ', error);
return;
}
To do the same thing using a stream:
const options = {
uri: url, /* Set url here. */
body: fs.createReadStream(fileName),
headers: {
'Content-Type': 'application/octet-stream'
}
};
request.post(options, (error, response, body) => {
if (error) {
console.log('Error: ', error);
return;
}
..
I have the following code that takes base64 string, and send it to API that accepts binary. I am getting empty response from the api call
let base64String = event.base64String;
// pass the base64 string into buffer
let buffer = new Buffer(base64String, 'base64');
// TODO check file type
processImage(buffer)
.then(result => {
console.log("result are " + result);
callback(result);
}).catch(error => callback(error));
let processImage = function (buffer) {
// get the file extension
return new Promise((resolve, reject) => {
var options = {
method: 'POST',
url: 'https://<UR - not visible for privacy>',
headers:
{
'Content-Type': 'application/octet-stream'
},
body: buffer.toString('binary')
};
request(options, function (error, response, body) {
if (error) reject(error);
console.log(body);
resolve(body);
});
}
Equivalent in postman is that I simply specify binary in body and attach file, again post call but URL is removed from pic, the header is content-type: application/octet-stream, it works in postman but not in node.js
I'm trying to extract the body from the callback returned from a Lambda fuction. I am calling the function using the code below:
const pdfBuffer = await new Promise((resolve, reject) => {
lambda.invoke(params, function(err, data) {
if (err) {
console.log('STACK ERROR IS' + err, err.stack)
reject(err);
} else {
console.log('Returned DATA is: ' + JSON.stringify(data));
resolve(data);
}
});
});
Prescription.deletePrescription(programId);
const returnedPDF = JSON.parse(pdfBuffer.Payload)
response.status(200);
response.set({
'Content-Type': 'application/pdf',
'Content-Disposition': `attachment; filename="${filename}.pdf"`,
'X-Publish-Filename': `"${filename}.pdf"`,
});
response.end(new Buffer(returnedPDF.body, 'binary'));
And the Lambda callback function looks like this:
return callback(null, {
statusCode: 200,
body: data,
isBase64Encoded: true,
headers: {
'Content-Type': 'application/pdf',
},
})
The data object I am getting back looks like this:
{"StatusCode":200,"ExecutedVersion":"$LATEST","Payload":"{\"statusCode\":200,\"body\":\"JVBERi0xLjQKJdPr6eEKMSAwIG9iago8PC9DcmVhdG9yIChDa=\",\"headers\":{\"Content-Type\":\"application/pdf\"}}"}
I've tried a number of things to get the body of this nested object? Including JSON.parse() as I thought that it was stringified, however I'm not having any luck.
Many thanks in advance.
I have a need to send data from my NodeJS server to an outside server. I have tried many codes and searched for this alot, but not getting any proper working example or its not working in my case.
Here is my code:
app.get('/getFrom', function (req, res) {
var request = require('request');
// Try 1 - Fail
/*var options = {
url: 'http://example.com/synch.php',
'method': 'POST',
'body': {"nodeParam":"working"}
};
request(options, callback);
*/
// Try 2 - Fail
/* request({
// HTTP Archive Request Object
har: {
url: 'http://example.com/synch.php',
method: 'POST',
postData: {
params: [
{
nodeParam: 'working'
}
]
}
}
},callback)*/
function callback(error, response, body) {
if (!error && response.statusCode == 200) {
console.log("body " + body); // Show the HTML for the Google homepage.
res.send(body);
}
else{
console.log("Error " + error);
res.send(error);
}
}
/* ------ HTTP ------ */
var postData = querystring.stringify({
'nodeParam' : 'Hello World!'
});
// try 3 - Fail
/*var optionsHTTP = {
hostname: 'http://example.com',
port: 80,
path: '/synch.php',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(postData)
}
};
var req1 = http.request(optionsHTTP, function(res1){
console.log('STATUS: ' + res1.statusCode);
console.log('HEADERS: ' + JSON.stringify(res1.headers));
res1.setEncoding('utf8');
res1.on('data', function(chunk){
console.log('BODY: ' + chunk);
});
res1.on('end', function(){
console.log('No more data in response.')
})
});
req1.on('error',function(e){
console.log('problem with request:' + e.message);
});
// write data to request body
req1.write(postData);
req1.end();*/
/* ------ /HTTP ------ */
Please let me know where I am wrong
Not sure why exactly your request might be failing, but this is a simple and straightforward sample on using the request module in npm:
var request = require('request');
var postData = {
name: 'test123'
}
request({
url: 'http://jsonplaceholder.typicode.com/posts',
method: 'POST',
data: JSON.stringify(postData)
}, function(err, response) {
if (err) {
return console.error(err);
};
console.log(JSON.stringify(response));
})
This snippet makes a request to a rest API and display the result on the console. The response data is available in the response.body property.
I found a working and tested solution :
request({
url: 'http://example.com/synch.php', //URL to hit
qs: {nodeParam: 'blog example', xml: xmlData}, //Query string data
method: 'POST', //Specify the method
},callback);
I'm trying to upload a video to vimeo with nodejs (https://developer.vimeo.com/apis/advanced/upload at step 3) . This is what I currently do:
Firstly I call the function to read the file:
var options = {
hostname : dataObject.ticket.host,
path : '/upload?ticket_id=' + dataObject.ticket.id,
port : 8080,
method: 'POST'
}
postMovie(options);
I get these parameters from my object:
{
"generated_in": "0.0308",
"stat": "ok",
"ticket": {
"endpoint": "http://126535.cloud.vimeo.com:8080/upload?ticket_id=9d818e8bd066dfd54e53f1be2fa3f958",
"endpoint_secure": "https://126535.cloud.vimeo.com/upload?ticket_id=9d818e8bd066dfd54e53f1be2fa3f958",
"host": "126535.cloud.vimeo.com",
"id": "9d818e8bd066dfd54e53f1be2fa3f958",
"max_file_size": "26843545600"
}
}
This function is called :
function postMovie(options){
// This is an async file read
fs.readFile('public/uploads/4363066343.mp4', function (err, data) {
if (err) {
console.log("FATAL An error occurred trying to read in the file: " + err);
process.exit(-2);
}
// Make sure there's data before we post it
if(data) {
PostData(data,options);
}
else {
console.log("No data to post");
process.exit(-1);
}
});
};
When the file is read:
function PostData(data,options) {
var headers = {
'Content-Type': 'video/mp4',
'Content-Length': data.length
}
options.headers = headers
console.log(options)
// Set up the request
var post_req = http.request(options, function(res) {
res.on('data', function (chunk) {
console.log('Response: ' + chunk);
});
});
// post the data
post_req.write(data);
post_req.end();
post_req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
}
My post_req.on(error) logs this:
problem with request: write EPIPE
problem with request: write EPIPE
I understand this is because of a time-out at the serverside.
I assume my request is not well formed.
Can someone point out what I did wrong ?
The upload operation will be much simpler with the request module.
var inspect = require('eyespect').inspector();
var request = require('request')
var path = require('path')
var fs = require('fs')
var filePath = path.join(__dirname, '../public/uploads/foo.mp4')
fs.stat(filePath, function(err, stats) {
if (err) {
inspect(err, 'error stating file')
return
}
var fileSize = stats.size
var url = 'https://126535.cloud.vimeo.com/upload?ticket_id=9d818e8bd066dfd54e53f1be2fa3f958'
var opts = {
url: url,
method: 'post',
headers: {
'Content-Length': fileSize,
'Content-Type': 'foo'
}
var r = request(opts)
// pipe the file on disk to vimeo
var readStream = fs.createReadStream(filePath)
readStream.pipe(r)
readStream.on('error', function (err) {
inspect(err, 'error uploading file')
})
readStream.on('end', function (err) {
inspect('file uploaded correctly')
})
})
Request also allows you to set the timeout option as well if the file is big and thus takes a long time to upload