Node Express.js - Download file from memory - 'filename must be a string'

app.get('/download', (request, response) => {
  const fileData = 'SGVsbG8sIFdvcmxkIQ=='
  const fileName = 'hello_world.txt'
  const fileType = 'text/plain'

  response.writeHead(200, {
    'Content-Disposition': `attachment; filename="${fileName}"`,
    'Content-Type': fileType,
  })

  const download = Buffer.from(fileData, 'base64')
  response.end(download)
})

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]).