NodeJS server Write response and start a file download - node.js

I'm creating a simple file conversion tool for a in-company service.
I'd created a http server where any user is able to upload a file through a form and them the server responds the request with the converted file download.
I Would like to write the conversion summary on the screen and them start the download. not just start the file download.
My code is:
createServer(function(req, res) {
var form = new IncomingForm();
form.parse(req, function(err, fields, files) {
var path = files.filetoupload.path;
var result = dataConverter.parse(path); // File data conversion
res.writeHead(200);
res.write(result.summary);
res.writeHead(200, { "Content-Type": "application/force-download", "Content-disposition": "attachment; filename=outputfile.csv" });
res.write(result.data);
res.end();
});
but i'm getting the fallowing response
ERR_INVALID_CHUNKED_ENCODING
How can I write those two responses to the user?

This is not possible without some client Javascript or something like this.
The content should be a file or write to the "page".
Te best solution was to create a temporary file to download and them send response to the page.

Related

Node buffer doesn't properly download file?

I'm successfully sending a get request that generates a pdf on the server, which I now want to send back to client and download it on their browser. The npm pdf generating library I'm using is called html-pdf and has the following options:
pdf.create(html).toFile([filepath, ]function(err, res){
console.log(res.filename);
});
pdf.create('<h1>Hi</h1>').toBuffer(function(err, buffer){
console.log('This is a buffer:', Buffer.isBuffer(buffer));
});
When I use the toFile option, the file gets correctly generated, however, when I use the toBuffer option and send that back to the user, the resulting pdf is blank.
I send the buffer to the user from my ajax handler like this:
module.exports = function(req, res) {
pdf.create(html).toBuffer(function(err, buffer){
res.setHeader('Content-Disposition', 'attachment; filename=panda.pdf');
res.setHeader('Content-Type', 'application/pdf');
res.send(buffer)
});
};
which gets received on the client here:
$.get('generatePdf', function(data, status) {
const url = window.URL.createObjectURL(new Blob([data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', 'file.pdf');
document.body.appendChild(link);
link.click();
})
For some reason though the pdf that is downloaded is blank. Does anyone know what I might be doing wrong?
My downloaded file is corrupt according to this online pdf validator with the following errors:
Result Document does not conform to PDF/A. Details Validating file
"file (8).pdf" for conformance level pdf1.4
The 'xref' keyword was not found or the xref table is malformed. The
file trailer dictionary is missing or invalid. The "Length" key of the
stream object is wrong. Error in Flate stream: data error. The
document does not conform to the requested standard. The file format
(header, trailer, objects, xref, streams) is corrupted. The document
does not conform to the PDF 1.4 standard.

How to download a multipart wav file from cloudant database and save locally using Node JS and REST API?

I am stuck in retrieving multipart from cloudant using Node JS API. Hence, I used REST API to download the wav file from cloudant database. But its not downloading wav file from https URL. When I enter the https URL directly in browser, it prompts me to save file locally. So, the URL is correct.
Here is the code for REST API:
var request1 = require('request');
var filestream = fs.createWriteStream("input.wav");
var authenticationHeader = "Basic " + new Buffer(user + ":" + pass).toString("base64");
request1( { url : "example.com/data/1533979044129/female";, headers : { "Authorization" : authenticationHeader } },
function (error, httpResponse, body) {
const statusCode = httpResponse.statusCode;
httpResponse.pipe(filestream);
httpResponse.on('end', function () {
console.log("file complete");
filestream.close();
}); });
The file size of input.wav is 0. Its not downloading file. Please help.
Your callback has an error argument, which you are completely ignoring. Do something with this error, like print it out so your problem can tell you what you're doing wrong. I definitely see at least 1 problem in your source, and the error from request should tell you what it is.
Edit On second thought the above code shouldn't even execute. You should share code that you tested yourself. There's typos in there.

How to attach a file to a response in REST call node js

I have a file in my local drive (say test.txt) and I am trying to attach this file in a response to a REST service. I have tried resp.writeHead, and rest.attachment('./test.txt'); etc. I am sure I am missing something here. I am getting status 200 in my response on Poster window but not getting the file. Can any one help where I am missing?
app.get('/getFile', function (req, resp) {
res.setHeader('Content-disposition', 'attachment; filename=' + '/MyDisk/test5.txt');
filestream = fs.createReadStream('/MyDisk/test5.txt');
filestream.pipe(resp);
resp.status(200);
resp.end();
});
Try adding this before sending out the response:
var filename = "test5.txt";
resp.setHeader('Content-disposition', 'attachment; filename=' + filename);
resp.setHeader('Content-type', 'text/plain');
Content Disposition Header lets the user save the file to their computer and then decide how to use it, instead of the browser trying to use the file.
Although you are adding the Content Disposition Header, you are adding it to a different object. Make sure you add the headers to the resp object and not the res object.

Node.js - Stream Binary Data Straight from Request to Remote server

I've been trying to stream binary data (PDF, images, other resources) directly from a request to a remote server but have had no luck so far. To be clear, I don't want to write the document to any filesystem. The client (browser) will make a request to my node process which will subsequently make a GET request to a remote server and directly stream that data back to the client.
var request = require('request');
app.get('/message/:id', function(req, res) {
// db call for specific id, etc.
var options = {
url: 'https://example.com/document.pdf',
encoding: null
};
// First try - unsuccessful
request(options).pipe(res);
// Second try - unsuccessful
request(options, function (err, response, body) {
var binaryData = body.toString('binary');
res.header('content-type', 'application/pdf');
res.send(binaryData);
});
});
Putting both data and binaryData in a console.log show that the proper data is there but the subsequent PDF that is downloaded is corrupt. I can't figure out why.
Wow, never mind. Found out Postman (Chrome App) was hijacking the request and response somehow. The // First Try example in my code excerpt works properly in browser.

Prompt a csv file to download as pop up using node.js and node-csv-parser (node module)

Recently I have started working with node.js. While going through a requirement in one of my projects I am facing an issue where I should be able to write some data to a csv file dynamically and let it prompt as a popup to download for user (with save and cancel options - as we normally see). After googling for some time I decided to use csv npm module https://github.com/wdavidw/node-csv-parser. I am able to write data into a file and save it using this module. I want to prompt a popup for saving this file with/without saving the file.
my code looks something like this:
// Sample Data
var data = [["id", "subject1", "subject2", "subject3"], ["jack", 85, 90, 68], ["sam", 77, 89, 69]]
// Server Side Code
var csv = require('../../node_modules/csv');
var fs = require('fs');
createCSV = function(data, callback) {
csv().from(data).to(fs.createWriteStream('D:/test.csv')) // writing to a file
}
// Client side call sample
$("#exportToCSV").click(function() {
callToServer.createCSV(data);
return false;
});
This is working good as far as writing the csv file is concerned.
I want to prompt this file immediately to download for users.
If this can be done without saving the file, that will be great.
How can I set content-type and content-disposition as we do in PHP
Any help is greatly appreciated.
-Thanks
Manish Kumar's answer is spot on - just wanted to include a Express 4 syntax variant to accomplish this:
function(req, res) {
var csv = GET_CSV_DATA // Not including for example.
res.setHeader('Content-disposition', 'attachment; filename=testing.csv');
res.set('Content-Type', 'text/csv');
res.status(200).send(csv);
}
I did it something like this :
http.createServer(function(request, response) {
response.setHeader('Content-disposition', 'attachment; filename=testing.csv');
response.writeHead(200, {
'Content-Type': 'text/csv'
});
csv().from(data).to(response)
})
.listen(3000);
Following solution is for Express
Express is evolved, instead of setting attachment and content type header, directly use attachment api http://expressjs.com/4x/api.html#res.attachment
Note: attachment() don't transfer the file, it just sets filename in header.
response.attachment('testing.csv');
csv().from(data).to(response);
Express-csv is a great module for writing csv contents to stream from a node.js server, which will be sent as a response to the client (and downloaded as a file). Very easy to use.
app.get('/', function(req, res) {
res.csv([
["a", "b", "c"]
, ["d", "e", "f"]
]);
});
The docs: https://www.npmjs.com/package/express-csv
When you pass an object, you need to prepend the headers explicitly (if you want them). Here's my my example using npm mysql
router.route('/api/report')
.get(function(req, res) {
query = connection.query('select * from table where table_id=1;', function(err, rows, fields) {
if (err) {
res.send(err);
}
var headers = {};
for (key in rows[0]) {
headers[key] = key;
}
rows.unshift(headers);
res.csv(rows);
});
});
Check out this answer: Nodejs send file in response
Basically, you don't have to save the file to the hard drive. Instead, try sending it directly to the response. If you're using something like Express then it would look something like this:
var csv = require('csv');
req.get('/getCsv', function (req, res) {
csv().from(req.body).to(res);
});

Resources