Downloading S3 file as attachment using knox/node.js passthrough - node.js

I am trying to get downloading files from S3 via node/knox working. My javascript call is working and successfully downloads the file, but I want to download it as an attachment. I have tried setting the headers to 'Content-disposition': 'attachment; filename=myfile.zip', but it doesn't seem to be working. Here is my sample code:
var mimetype = mime.lookup(product.filename);
var headers = {
'Content-disposition': 'attachment; filename=' + product.filename,
'Content-type': mimetype
};
var get = knox.getFile(product.filename, function(err, result){
if(err) { return next(err); }
res.setHeader('Content-disposition', 'attachment; filename=' + product.filename);
res.setHeader('Content-type', mimetype);
result.pipe(res);
});
I have also tried setting those headers on the knox call, but still won't download as attachment.

So it looks like the problem wasn't my server at all, as I was unaware that you cannot use xhr (i.e. $resource with Angular) to download files as attachments. The simplest way I have found to get around this so far, is to only use xhr to validate the download, returning a token to the user which can be used non-xhr to get the actual file.

Related

nodejs cant open pdf file after download

I am using nest js, I have converted html file and saved to pdf on my localhost when opening the pdf file from the save location it is fine,
but when I am downloading I'm unable to open the file.
My api controller answers that the file is download successfully.
async exportPDF(#Res({ passthrough: true }) res: Response, #Body() dto: ExportReadingsPDFDto) {
const stream = await this.metersService.exportPDF(dto);
const filename = stream.replace(/^.*[\\\/]/, "");
const fileReadStream = fs.createReadStream(stream, { encoding: "base64" });
const stat = fs.statSync(stream);
res.set({
"Content-Type": "application/pdf",
"Content-Length": stat.size,
"Content-Disposition": 'attachment; filename="' + filename + '"'
});
fileReadStream.pipe(res);
}
Please help, I couldn't find any other example for creating pdf files and sending them to the user
You can simply create the PDF file within server, then using this piece of code you can download it as a response for the user.
const filename = '123.pdf';
res.setHeader('Content-disposition', 'attachment; filename=' + filename);
const filestream = createReadStream('files/' + filename);
filestream.pipe(res);

Not Getting Response From Another Nodejs Server?

I am learning Nodejs. I am facing a small problem. I am uploading file to google cloud service. All types of files are uploading and I am getting signed URL of file. I am sending the signed URL from one nodejs server to another nodejs server. While uploading jpg or png file its success and getting response back to the another server.
But the issues is that, when I upload xlsx (excel file) I am not getting response to the another server. Its happing only while I upload the excel file only.
Any solution for that?
First Nodejs Server from where File is uploaded to GCS->
if(is_valid_request){
interface.gcpFileUpload(req, (data)=>{
console.log("response = "+ JSON.stringify(data));
res.json(data)
})
} else{
res.json({success:0,err:"request is not valid"});
}
Another server where I want to get response->
getResponse(source, filename, destination, bucket_name, json_url, callback) {
var formData = {
file: fs.createReadStream(source),
filename: filename,
json_url: json_url,
destination: destination,
bucket_name: bname
}
var options = {
'method': 'POST',
'url': endpoint_of_another_server,
'headers': {
'api_key': key,
'Content-Type': 'application/json',
},
formData: formData,
}
console.log("I AM RUNNING TILL HERE")
request(options, function (error, response) {
console.log("WE ARE GETTING SOME RESPONSE " + response);
return callback(response.body);
})
}
It is hard to conclude on something without looking at the code snippets. But as per your problem statement, if it is only issue with *.xlsx (excel file) then it may have one of the below issue:
You may need to allow *.xlsx file extension in your code
If the file extension is already allowed, then there may be issue with the size of the file (assuming if it is having GBs of data)
Nevertheless, we can help you out more if you provide more details of code snippet.

Sending pdf files to user from nodejs to reactjs

I have pdf documents stored in the file system on the server side.
I need to let the user download one of them when he/she clicks on download.
The problem is that I know how to send a file from NodeJS to browser but here the request will be made by a ReactJS axios request. So when I send a file, the response will go to react. How do I send that pdf file to the user? Do I access the file system directly using my front end code?
I get the following in the browser console when I log the response after I do res.sendFile(file_path) in NodeJS
How do I process this so that I can make the user download the pdf?
You can use file-saver to download the file. Below is the function I'm using for pdf download. (response.data is the Buffer that nodejs sends back as a response)
import FileSaver from 'file-saver';
...
_onPdfFetched() {
FileSaver.saveAs(
new Blob([response.data], { type: 'application/pdf' }),
`sample.pdf`
);
}
or you can just show pdf to the user
window.open(response.data, '_blank');
Edit
The axios call should be like this:
axios.get(url, {
responseType: 'arraybuffer',
headers: {
Accept: 'application/pdf',
},
});
Edit 2
The nodejs code should be like this:
router.post('/api/downloadfile',(req, res, next) => {
const src = fs.createReadStream('path to sample.pdf');
res.writeHead(200, {
'Content-Type': 'application/pdf',
'Content-Disposition': 'attachment; filename=sample.pdf',
'Content-Transfer-Encoding': 'Binary'
});
src.pipe(res);
});

Google Cloud Print API - white page when printing PDF

I want to send a PDF file to be printed using the Google Cloud Print API. The code bellow will give me a positive message telling me that one page was generate. When I go and check what came out, I gate an empty page.
The same result happens if I save the print on Google Drive.
The code
unirest.post('https://www.google.com/cloudprint/submit')
.header('Authorization', 'Bearer ' + token)
.header("Accept-Charset", "utf-8")
.field('xsrf', xsrf_token)
.field('printerid', printerId)
.field('ticket', '{"version": "1.0", "print": {}}')
.field('title', 'Test from Simpe.li')
.field('contentType', 'application/pdf')
.attach('content', buffer)
.end(function (res) {
console.log(res);
});
I know that what I'm sending is a PDF, because when I change the
.field('contentType', 'application/pdf')
to
.field('contentType', 'text/plain')
I will get 53 pages of text which is the raw content of the PDF file.
Question
What I'm doing wrong?
Tech spec
NodeJS v4.1.1
Unirest v0.4.2
It turns out that the Google documentation left some key information out. To send a binary type data, like a PDF, you need to convert the file to base64. In addition to that you need to tell Google that you are going to send them a base64 blob with the add field contentTransferEncoding and set the value to base64.
Another important thing. There is a bug in Unirest (for NodeJS at least), where sending a base64 file won't set the Content-Size header. Nor even setting your own will fix the problem. To circumvent this issue I had to switch to Request. The following code shows a post to Google Cloud Print that works:
let buffer64 = buffer.toString('base64');
let formData = {
xsrf: xsrf_token,
printerid: printerId,
ticket: '{"version": "1.0"}',
title: 'Test Print',
contentTransferEncoding: 'base64',
contentType: 'application/pdf',
content: buffer64
};
let headersData = {
'Authorization': 'Bearer ' + token
};
request.post({
url: 'https://www.google.com/cloudprint/submit',
headers: headersData,
formData: formData
}, function (err, httpResponse, body) {
if (err) {
return console.error('upload failed:', err);
}
console.log('Upload successful! Server responded with:', body);
});
I hope this will help others :)

Express.js - how to download base64 string as PDF file?

I have pdf file encoded as base64 string. How to download this string to the browser as file in .pdf format?
What I have already tried:
res.set('Content-Disposition', 'attachment; filename="filename.pdf"');
res.set('Content-Type', 'application/pdf');
res.write(fileBase64String, 'base64');
I ended up to decode the pdf first and then send it to the browser as binary as follows:
(For simplicity I use node-http here but the functions are available in express as well)
const http = require('http');
http
.createServer(function(req, res) {
getEncodedPDF(function(encodedPDF) {
res.writeHead(200, {
'Content-Type': 'application/pdf',
'Content-Disposition': 'attachment; filename="filename.pdf"'
});
const download = Buffer.from(encodedPDF.toString('utf-8'), 'base64');
res.end(download);
});
})
.listen(1337);
What drove me nuts here was the testing with Postman:
I was using the Send Button instead of the Send and Download Button to submit the request:
Using the Send button for this request causes that the pdf file becomes corrupted after saving.
Just a reference for Express. This answer is based on ofhouse's answer.
This solution is downloading a png file. I was missing the "Content-Disposition" part, which makes the browser not display the png, but download it. png is a Buffer-object.
app.get("/image", (req, res) => {
getPng()
.then((png) => {
res.writeHead(200, {
"Content-Type": png.ContentType,
"Content-Length": png.ContentLength,
"Content-Disposition": 'attachment; filename="image.png"',
});
res.end(png.Body);
})
.catch(() => {
res.send("Couldn't load the image.");
});
});

Resources