Alex Turdean
Alex Turdean

Reputation: 69

File download in Node JS

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

Answers (2)

Bhuvanachandu
Bhuvanachandu

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

Souvik Dey
Souvik Dey

Reputation: 703

Just use res.download(<filepath>).

https://expressjs.com/en/api.html#res.download

Upvotes: 1

Related Questions