request-promise download pdf file - node.js

I received multiple pdf files and must download it from a REST-API.
After auth and connect I try to download the file with request-promise:
const optionsStart = {
uri: url,
method: 'GET',
headers: {
'X-TOKEN': authToken,
'Content-type': 'applcation/pdf'
}
}
request(optionsStart)
.then(function(body, data) {
let writeStream = fs.createWriteStream(uuid+'_obj.pdf');
console.log(body)
writeStream.write(body, 'binary');
writeStream.on('finish', () => {
console.log('wrote all data to file');
});
writeStream.end();
})
The request create a pdf (approximately 1-2MB) but I can't open it. (Mac Preview show blank pages and adobe show = >
There was an error opening this document. There was a problem reading
this document (14).
I have no information about the API Endpoint where I download the files. Just have this curl:
curl -o doc.pdf --header "X-TOKEN: XXXXXX"
http://XXX.XXX/XXX/docs/doc1
Where is my mistake?
Update:
I opened the file in edit and the file looks like that:
Don't have any experience with that :-)

Add encoding: 'binary' to your request options:
const optionsStart = {
uri: url,
method: "GET",
encoding: "binary", // it also works with encoding: null
headers: {
"Content-type": "application/pdf"
}
};

Add encoding: null to your request options:
const optionsStart = {
uri: url,
method: "GET",
encoding: null,
headers: {
"Content-type": "application/pdf"
}
};
Then, turn the response into a Buffer (if necessary):
const buffer = Buffer.from(response);

try this
const optionsStart = {
uri: url,
method: 'GET',
headers: {
'X-TOKEN': authToken,
'Content-type': 'application/pdf'
},
encoding: null
}
request(optionsStart, (err, resp) => {
let writeStream = fs.createWriteStream(uuid + '_obj.pdf');
writeStream.write(resp.body, 'binary');
writeStream.on('finish', () => {
console.log('wrote all data to file');
});
writeStream.end();
})

Related

Converting image URL to .png file using NodeJS

I am currently working on an application which takes in image URLs in this format:
https://replicate.delivery/pbxt/Y45OPyjFe92FLqemk1Mmsr69gzruylefj5SxKqJInMmxCyABB/out-0.png
And need to send it to an API to check if it is explicit content. The issue is that the API only accepts .png or .jpg files and not an image URL. How can I convert this image URL into a sendable file?
This is what their docs say:
const axios = require('axios').default;
const fs = require("fs");
const FormData = require("form-data");
const form = new FormData();
form.append("providers", 'amazon, google');
form.append("file", fs.createReadStream("🖼️ path/to/your/image.png"));
const options = {
method: 'POST',
url: 'https://api.edenai.run/v2/image/explicit_content',
headers: {
authorization: 'Bearer 🔑 Your_API_Key',
'Content-Type': 'multipart/form-data; boundary=' + form.getBoundary()
},
data: form
};
axios
.request(options)
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.error(error);
});
However, I do not have the path to the file and instead solely the image URL. Any help would be greatly appreciated!
You need to make an extra request to get the image first, keep it in memory (alternatively, you could save the file and then read it with fs), and then make another request, which sends the image to the checking endpoint.
With axios, you can get the image as a stream, and then just pass it along with form-data.
Try this:
// get image as a stream
const getImgOptions = {
method: 'GET',
url: 'https://replicate.delivery/pbxt/Y45OPyjFe92FLqemk1Mmsr69gzruylefj5SxKqJInMmxCyABB/out-0.png',
responseType: 'stream'
};
let img;
try {
img = await axios.request(getImgOptions);
// got the image, now send it for checking
let uploadImg;
try {
const form = new FormData();
form.append("providers", 'amazon, google');
form.append("file", img.data);
const postImgOptions = {
method: 'POST',
url: 'https://api.edenai.run/v2/image/explicit_content',
headers: {
authorization: 'Bearer 🔑 Your_API_Key',
'Content-Type': 'multipart/form-data; boundary=' + form.getBoundary()
},
data: form
};
uploadImg = await axios.request(postImgOptions);
// do something with the result
console.log('check response: ', uploadImg.data);
} catch (error) {
console.error(error);
}
} catch (error) {
console.error(error);
}

Axios FormAppend post method and node.js

I trigger / upload in node.js by calling the submit function inside a class. But in Node.js, req.body is empty. In fact, I append data to FormData in the submit function and send it to node.js. Where am I doing the problem?
Class
submit(){
const data = new FormData()
data.append('file', this.state.selectedFile)
data.append('ID', uniqid())
let url = "http://localhost:5000/upload";
axios({
method: "POST",
url: url,
data: data,
headers: {
"Content-Type": "application/json"
}
}).then(res => {
});
}
Node.js
app.post('/upload', (req, res) => {
axios.post('https://....php', req.body, {
}).then(function (response) {
}).catch(function (error) {
console.log('errorserver', error);
});
});
Try to put file after text like this.
submit(){
const data = new FormData()
data.append('ID', uniqid())
data.append('file', this.state.selectedFile)
let url = "http://localhost:5000/upload";
axios({
method: "POST",
url: url,
data: data,
headers: {
"Content-Type": "application/json"
}
}).then(res => {
});
}

Cloudconvert - Invalid signature error when using request-promise to upload via API

I'm attempting to upload a pdf through the cloudconvert API using nodeJS and request-promise. The request to get the upload URL and parameters is successful, but when I attempt to pass the data I get a 401 - "FormPost: Invalid Signature" error, even though I'm using the signature returned from the first request.
...
pdfToPng: function(pdfBuffer, apiKey) {
return new Promise(async (resolve, reject) => {
const cloudConvert = new CloudConvert(apiKey);
let response = JSON.parse(
await request.post('https://api.cloudconvert.com/v2/import/upload', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-type': 'application/json',
},
}));
let fileUrl = response.data.result.form.url;
let params = response.data.result.form.parameters;
let fileUpload = await request.post({
url: fileUrl,
formData: {
"expires": params.expires,
"max_file_count": params.max_file_count,
"max_file_size": params.max_file_size,
"signature": params.signature,
"file": {
value: pdfBuffer.toString('base64'),
options: {
filename: 'invoice.pdf',
contentType: 'application/pdf'
}
}
}
}).catch((err) => {
console.log('ERROR UPLOADING FILE: ', err); //<-- 401 Error here
reject(err);
})
console.log('FILE UPLOAD RESPONSE: ', fileUpload);
...
You need to pass all parameters of response.data.result.form.parameters to formData, not just the named ones:
let fileUpload = await request.post({
url: fileUrl,
formData: {
...response.data.result.form.parameters,
"file": {
value: pdfBuffer.toString('base64'),
options: {
filename: 'invoice.pdf',
contentType: 'application/pdf'
}
}
}

Why i am getting unable to open document error or blank pdf in opening a pdf on client side?

I am hitting a get api in react similar to http://www.orimi.com/pdf-test.pdf which needs some secret information which is available only at middleware written in node. I want to open the pdf on client side(browser). So I am hitting the proxy get api which will hit the middleware and middleware will hit the backend server, but I am getting unable to open document and blank pdf. Can anyone tell me what is wrong with this code?
fetch(pdfApiMiddlewareUrl, {
method: "GET",
headers: {
"Content-Type": "application/pdf",
'Content-Disposition': 'inline; filename=your_file_name'
},
responseType : 'blob'
})
.then(res => res.blob())
.then(response => {
var blobUrl = URL.createObjectURL(response);
window.open(blobUrl);
})
.catch(error => {
console.log("HEREEEEEEEE");
console.log(error);
});
MIDDLEWARE CODE:
var urlEndPointsToHit = decodeURIComponent(req.query.urlToHit);
var url = urlEndPointsToHit+'?secret='+secretInfo;
var options;
options = {
url: url,
method: 'GET',
headers: {
'Content-type': 'application/pdf'
},
};
if(options) {
options.qs = req.query || {};
}
request(options, function(err, resp, body) {
req.locals = body;
res.setHeader('Content-Type', 'application/pdf');
res.setHeader('Cache-Control', 'no-cache');
next();
});

Nodejs Post attachment to JIRA

I am receiving http POST response OK 200, but I see no file present on JIRA issue. From my research I can understand that it could be some problem with formData I am sending with request. Below is my code:
var newBuffer = new Buffer(req.Payload, 'base64');
var myReadableStreamBuffer = new streamBuffers.ReadableStreamBuffer({
frequency: 10, // in milliseconds.
chunkSize: 2048 // in bytes.
});
// With a buffer
myReadableStreamBuffer.put(newBuffer);
var formData = {
'file': {
'content': myReadableStreamBuffer,
'filename': req.FileName,
'mimeType': req.MimeType //mimeType from JSON
}
};
var options = {
url: 'https://comapny.atlassian.net/rest/api/2/issue/' + req.ReferenceId + '/attachments',
method: "POST",
json: true,
headers: {
'ContentType': 'multipart/form-data',
'Authorization': 'Basic ' + new Buffer(config.jira.jiraUser.userName + ':' + config.jira.jiraUser.password).toString('base64'),
'X-Atlassian-Token': 'nocheck'
},
formData: JSON.stringify(formData)
};
request(options,
function (error, response, body) {
if (error) {
errorlog.error(`Error Message : PostAttachmentToCSMS : ${error}`);
return response.statusCode;
}
else {
successlog.info(`Attachment posted for issue Key: ${req.ReferenceId} ${response.statusMessage}`);
return response.statusCode;
}
});
I can write file from myReadableStreamBuffer, so that seems ok. Please help me to identify the problem. Many thanks!
After spending some more time on it, I have found the correct format for formData:
var newBuffer = new Buffer(req.Payload, 'base64');
var formData = {
file: {
value: newBuffer,
options: {
filename: req.FileName,
contentType: req.MimeType
}
}
};
For whom like me getting errors with this API.
After struggling so many hrs on this thing, I finally found this works like a charm. I've got "XSRF check failed" 403/404 error message before writing this code.
// Don't change the structure of formData.
const formData = {
file: {
value: fs.createReadStream(filepath),
options: {
filename: filename,
contentType: "multipart/form-data"
}
}
};
const header = {
"Authentication": "Basic xxx",
// ** IMPORTANT **
// "Use of the 'nocheck' value for X-Atlassian-Token
// has been deprecated since rest 3.0.0.
// Please use a value of 'no-check' instead."
"X-Atlassian-Token": "no-check",
"Content-Type": "multipart/form-data"
}
const options = {
url: "http://[your_jira_server]/rest/api/2/issue/[issueId]/attachments",
headers: header,
method: "POST",
formData: formData
};
const req = request(options, function(err, httpResponse, body) {
whatever_you_want;
};
I was able to post attachments to JIRA using axios in the following way:
const axios = require('axios');
const FormData = require('form-data')
const fs = require('fs');
const url = 'http://[your_jira_server]/rest/api/2/issue/[issueId]/attachments';
let data = new FormData();
data.append('file', fs.createReadStream('put image path here'));
var config = {
method: 'post',
url: url,
headers: {
'X-Atlassian-Token': 'no-check',
'Authorization': 'Basic',
...data.getHeaders()
},
data: data,
auth: {
username: '',
password: ''
}
};
axios(config)
.then(function (response) {
res.send({
JSON.stringify(response.data, 0, 2)
});
})
.catch(function (error) {
console.log(error);
});

Resources