Node Express.js - 从内存下载文件 - 'filename必须是一个字符串'

Kar*_*ric 10 download node.js express

我正在尝试将内存中的数据打包成文本文件并将其发送给用户,从而触发文件下载.

我有以下代码:

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 );

});
Run Code Online (Sandbox Code Playgroud)

它不断抛出错误,说Content-disposition的filename参数必须是一个字符串.fileName肯定是一个字符串,所以我不确定发生了什么.

sha*_*ncs 23

更新:

感谢@jfriend00的建议,将Buffer作为文件直接发送到客户端更好,更有效,而不是先将其保存在服务器磁盘中.

要实现,stream.PassThrough()并且pipe()可以使用,下面是一个例子:

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);
});
Run Code Online (Sandbox Code Playgroud)

根据Express 文件,res.download()API是:

res.download(path [,filename] [,fn])

将路径中的文件作为"附件"传输.通常,浏览器会提示用户下载.默认情况下,Content-Disposition标头"filename ="参数是path(这通常出现在浏览器对话框中).使用filename参数覆盖此默认值.

请注意,第一个参数res.download()是"path",它表示服务器中要下载的文件的路径.在你的代码中,第一个参数是一个Buffer,这就是Node.js抱怨"filename参数必须是一个字符串"的原因 - 默认情况下,Content-Disposition标题"filename ="参数是path.

要使代码正常工作res.download(),您需要将fileData服务器保存为文件,然后res.download()使用该文件的路径调用:

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);
  });
});
Run Code Online (Sandbox Code Playgroud)

此外,请注意new Buffer(string[, encoding])现在已弃用.最好使用Buffer.from(string[, encoding]).

  • 应该有一种方法可以解决这个问题,而无需先将数据写入文件。此外,您的代码不会生成不会与其他请求冲突的唯一文件名,并且不会在适当的时间清理临时文件。 (5认同)

Die*_*emo 15

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)
})
Run Code Online (Sandbox Code Playgroud)

  • 不工作...我收到“Hello, World!”响应,但 chrome 没有打开保存文件弹出窗口...也没有自动保存文件... (2认同)