Reputation: 69
I am trying to implement a download router for a nodejs app. After several downloads my app crashes. Any advice?
app.route( "/download" )
.get( (req, res) => {
var filename = req.query.filename;
var file = __dirname + '/upload/' + filename;
var mimetype = mime.lookup(file);
res.setHeader('Content-disposition', 'attachment; filename=' + req.query.filename);
res.setHeader('Content-type', mimetype);
var filestream = fs.createReadStream(file);
filestream.pipe(decrypt).pipe(res);
})
I get this error:
Error [ERR_STREAM_WRITE_AFTER_END]: write after end
at writeAfterEnd (_stream_writable.js:243:12)
at Decipher.Writable.write (_stream_writable.js:291:5)
at ReadStream.ondata (_stream_readable.js:666:20)
at ReadStream.emit (events.js:182:13)
at addChunk (_stream_readable.js:283:12)
at readableAddChunk (_stream_readable.js:264:11)
at ReadStream.Readable.push (_stream_readable.js:219:10)
at fs.read (internal/fs/streams.js:196:12)
at FSReqCallback.wrapper [as oncomplete] (fs.js:473:5)
Emitted 'error' event at:
at Decipher.onerror (_stream_readable.js:690:12)
at Decipher.emit (events.js:182:13)
at writeAfterEnd (_stream_writable.js:245:10)
at Decipher.Writable.write (_stream_writable.js:291:5)
[... lines matching original stack trace ...]
at FSReqCallback.wrapper [as oncomplete] (fs.js:473:5)
UPDATE Someone asked about decrypt, the files are encrypted using crypto module:
var decrypt = crypto.createDecipher(algorithm, password);
Also, after reading res.end() is never sent after streaming a file to client i tried this:
var filestream = fs.createReadStream(file);
filestream.pipe(decrypt).pipe(res, {end: false});
filestream.on("close", function() {
res.status(200);
res.end();
});
filestream.on("error", function() {
res.status(400);
res.end();
});
It doesn't work :(, i get the same error
Upvotes: 3
Views: 4357
Reputation: 175
This error usually occurs when we are out of memory. So we have to close every stream after using it.
Streams are EventEmitters so you can listen to certain events.
app.route( "/download" ).get( (req, res) => {
var filename = req.query.filename;
var file = __dirname + '/upload/' + filename;
var mimetype = mime.lookup(file);
res.setHeader('Content-disposition', 'attachment; filename=' + req.query.filename);
res.setHeader('Content-type', mimetype);
var filestream = fs.createReadStream(file);
filestream.pipe(decrypt).pipe(res);
filestream.on("finish", function(){
res.send();
})
})
Upvotes: 1
Reputation: 703
Just use res.download(<filepath>)
.
https://expressjs.com/en/api.html#res.download
Upvotes: 1