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

前端 未结 2 747
悲&欢浪女
悲&欢浪女 2021-02-07 05:00

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(\'/downloa         


        
相关标签:
2条回答
  • 2021-02-07 05:16

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

    0 讨论(0)
  • 2021-02-07 05:33
    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)
    })
    
    0 讨论(0)
提交回复
热议问题