I'm trying to package data in memory into a text file and send it to the user, triggering a file download.
I have the following code:
app.get('/download', function(request, response){ fileType = request.query.fileType; fileName = ( request.query.fileName + '.' + fileType ).toString(); fileData = request.query.fileData; response.set('Content-disposition', 'attachment; filename=' + fileName ); response.set('Content-type', 'text/plain'); var fileContents = new Buffer(fileData, "base64"); response.status(200).download( fileContents ); });
It keeps throwing an error saying that Content-disposition's filename parameter must be a string. fileName is most certainly a string, so I'm not sure what is going on.
Downloading a file using node js can be done using inbuilt packages or with third party libraries. GET method is used on HTTPS to fetch the file which is to be downloaded. createWriteStream() is a method that is used to create a writable stream and receives only one argument, the location where the file is to be saved.
var path = require('path'); var mime = require('mime'); var fs = require('fs'); app. get('/download', function(req, res){ var file = __dirname + '/upload-folder/dramaticpenguin. MOV'; var filename = path. basename(file); var mimetype = mime.
Installing Express Use the following command to install express: npm install express --save.
Update:
Thanks to @jfriend00's advice, it is better and more efficient to directly send Buffer to client as file, instead of saving it first in server disk.
To implement, stream.PassThrough()
and pipe()
can be used, here is an example:
var stream = require('stream'); //... app.get('/download', function(request, response){ //... var fileContents = Buffer.from(fileData, "base64"); var readStream = new stream.PassThrough(); readStream.end(fileContents); response.set('Content-disposition', 'attachment; filename=' + fileName); response.set('Content-Type', 'text/plain'); readStream.pipe(response); });
According to Express document, res.download()
API is:
res.download(path [, filename] [, fn])
Transfers the file at path as an “attachment”. Typically, browsers will prompt the user for download. By default, the Content-Disposition header “filename=” parameter is path (this typically appears in the browser dialog). Override this default with the filename parameter.
Please note the first parameter of res.download()
is a "path", which indicates the path of file in server that would be downloaded. In your code, the first parameter is a Buffer, that's why Node.js complain that "filename parameter must be a string" -- By default, the Content-Disposition
header “filename=” parameter is path.
To make your code work using res.download()
, you need to save the fileData
in server as a file, and then invoke res.download()
with that file's path:
var fs = require('fs'); //... app.get('/download', function(request, response){ //... var fileContents = Buffer.from(fileData, "base64"); var savedFilePath = '/temp/' + fileName; // in some convenient temporary file folder fs.writeFile(savedFilePath, fileContents, function() { response.status(200).download(savedFilePath, fileName); }); });
Also, please note new Buffer(string[, encoding])
is deprecated now. It is better to use Buffer.from(string[, encoding])
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With