nodejs sending file to client hangs until server is killed - node.js

I am trying to send a csv file to the client.
When I do this, the download begins, but hangs on "starting...." and says it is transmitting at 0B/s.
When I kill the server, the file is transmitted and is all there.
What's causing this?
app.get('/weather_log.csv', function(req, res){
console.log('sending weather log')
filePath = 'weather_log.csv'
var file = fs.readFileSync(filePath, 'binary');
console.log(typeof(file))
res.setHeader('Content-Length', fs.statSync(filePath));
res.setHeader('Content-Type', 'text/csv');
res.setHeader('Content-Disposition', "attachment;filename=" + filePath);
res.write(file, 'binary');
res.end();
})
My guess is that res.end() is not firing or that the client doesn't realise that the file transfer is not complete for some other reason.

As per a0js, the answer was to use res.download(filePath).

Related

How to download image from node server sending image filename in HTTP post request from Angular 2

I want to download an image from node server when sending post request for image file name.But I couldn't get either save dialog box or direct download.I have a folder uploads from which I want to read the image and download.I am trying the code pasted over here.Please help me with a good solution.
router.post('/download', urlencodedParser, function(req, res) {
var img = path.resolve('uploads/' + req.body.file);
var filename = path.basename(img);
var mimetype = mime.lookup(img);
console.log(filename);
console.log(mimetype);
res.setHeader('Content-disposition', 'attachment; filename=' + filename);
res.setHeader('Content-type', mimetype);
var filestream = fs.createReadStream(img);
filestream.pipe(res);
res.on('finish', function(){
console.log("Download complete");
});
})

NodeJS - Serve file with throttled speed

I'm quite new to NodeJS and trying different stuff.
What I was able to do is to download a file going using the following code:
app.get('/download', function(req, res){
var file = 'public/songs/myfile.mp3';
var filename = path.basename(file);
var mimetype = mime.lookup(file);
res.setHeader('Content-disposition', 'attachment; filename=' + filename);
res.setHeader('Content-type', mimetype);
res.setHeader('Content-Length', file.length);
var filestream = fs.createReadStream(file);
filestream.pipe(res);
});
This works well, now what I'm trying to achive is see if it's possible to throttle the download speed. Like if someone tries to download the file it will download at max 1 Mbps (for example).
I've tried to use this code: https://gist.github.com/4poc/1454516
When I load the page it seems to load indefinetly, but I think that the problem is
filestream.pipe(limitStream);
Since that no response is given.
How can I implement what I would like to do? Or how I can fix the code I tried to use?
The req and res objects are streams, so you can pipe on the response:
var filestream = fs.createReadStream(file);
filestream.pipe(limitStream).pipe(res);
fwiw: every time you call pipe() you get back a new stream. The above is the same as this:
var filestream = fs.createReadStream(file);
var throttleStream = filestream.pipe(limitStream);
throttleStream.pipe(res);
This is important to understand because it's tempting to do this, but it won't do what you expect:
var filestream = fs.createReadStream(file);
filestream.pipe(limitStream);
filestream.pipe(res);

Prompt a download of PDF with Node.js

I am trying to prompt a download of a PDF generated on the server using Node.js. Currently I can save it to the server but not force a download.
I am using npm html-pdf and currently it is saving to the server with this code.
pdf.create(htmlbody).toStream(function(err, stream){
console.log(stream);
if (err) return next(err);
stream.pipe(fs.createWriteStream('./foo.pdf'));
res.status(200);
res.send('Success');
});
How can I make it force a download?
I tried setting headers like
res.setHeader('content-type', 'application/pdf');
res.setHeader("Content-Disposition", "attachment; filename="+pdfName+";");
I am testing on localhost but I don't presume this to be the issue.
You don't have to save it to the server (unless that is a business logic requirement). What you can do is simply this:
pdf.create(htmlbody).toStream(function(err, stream){
if (err) return next(err);
res.setHeader('Content-Type', 'application/pdf');
res.setHeader('Content-Disposition', 'attachment; filename='+pdfName+';');
stream.pipe(res);
});
Basically, all you need to do is set the appropriate headers and then pipe the stream you get from html-pdf to your res stream.
If you however need to save the PDF on the server first, then you'll have to write it to the file system and once it's done, read it back and send it over the response stream again.
Edit: Here's the code snippet with a full working example (running on Node v4.0.0).
var http = require('http');
var pdf = require('html-pdf');
const PORT = 8765;
var server = http.createServer((req, res) => {
var html = '<html><head><title>PDF Test</title></head><body><h1>Welcome</h1><p>This is a test to see if we can get <b>PDF generation</b> to work on the server side.</p><p>PDF files can be very tricky to do on the server so this will take a bit of <u>hit and trail</u> before we can be confident it works fine.</p></body></html>';
pdf.create(html).toStream((err, stream) => {
if (err) {
console.error(err);
res.status(500);
res.end(JSON.stringify(err));
return;
}
res.setHeader('Content-Type', 'application/pdf');
res.setHeader('Content-Disposition', 'attachment; filename=test-file.pdf;');
stream.pipe(res);
});
});
server.listen(PORT, () => {
console.log('Server listening on Port: %s', PORT);
});
Save the above as something like pdf.js and run in with node (node pdf.js) and open http://localhost:8765/. This should trigger a download in your browser.

res.download crashing the browser

Im trying to send a file on the server to the browser as a download. res.download is cashing the browser.
Any ideas?
Code
var filename = path.basename(userPathZip);
var mimetype = mime.lookup(userPathZip);
res.setHeader('Content-disposition', 'attachment; filename=test.zip');
res.setHeader('Content-type', mimetype);
var filestream = fsextra.createReadStream(userPathZip);
filestream.pipe(res);
in the network tab in chrome the response is 24mb which is the size of the file so im not sure whats goin on here
var filename = path.basename(userPathZip);
var mimetype = mime.lookup(userPathZip);
res.setHeader('Content-disposition', 'attachment; filename=test.zip');
res.setHeader('Content-type', mimetype);
var filestream = fsextra.createReadStream(userPathZip);
filestream.pipe(res);
it is res.pipe(filestream);
What would be the best was to serve files to admin only? Don't want the files making it to a public folder

Node.js throttle streams

I'm trying to create a Node.js HTTP file streaming server. I want to do the following:
sender --HTTP POST--> Node.js HTTP Server <--HTTP GET-- receiver
I have this already working with the following code:
var app = express();
// ...
app.post('/upload', function (req, res) {
// Get the `req` and `res` arguments of the HTTP GET request
var downloadRequest = getDownloadClientRequest();
// parse a file upload
var form = new formidable.IncomingForm();
form.onPart = function (part) {
if (!part.filename) {
// let formidable handle all non-file parts
form.handlePart(part);
return;
}
downloadRequest.res.writeHead(200, {
'Content-Disposition': 'attachment; filename=' + part.filename
});
part.on('data', function(data) {
downloadRequest.res.write(data);
});
part.on('end', function() {
downloadRequest.res.end();
});
};
form.parse(req, function (err, fields, files) {
res.writeHead(200);
res.write('Successfully streamed');
res.end();
});
});
app.get('/download', function (req, res) {
storeDownloadClientRequest(req, res);
});
What obviously happens is that if the uploading client is much faster than the downloading client, the upload completes very fast and my Node.js process keeps the whole file in memory until the downloading client finishes it.
How can I throttle the uploader's speed? I guess I can pause his stream every now and then but how do I know if the downloader's stream/buffer is filling up?
PS: I throttled the downloading client with wget --limit-rate=100k, if it helps.
part.pipe(downloadRequest) should automatically handle pausing/resuming when buffer is full.

Resources