Node Express.js - 从内存中下载文件 - '文件名必须是字符串'

时间:2017-08-28 15:05:31

标签: node.js express download

我试图将内存中的数据打包成文本文件并发送给用户,从而触发文件下载。

我有以下代码:

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

});

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

2 个答案:

答案 0 :(得分:12)

更新

感谢@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(res);
});

根据Express documentres.download() API是:

  

res.download(路径[,文件名] [,fn])

     

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

请注意res.download()的第一个参数是“路径”,它表示服务器中要下载的文件的路径。在你的代码中,第一个参数是一个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);
  });
});

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

答案 1 :(得分:10)

'\n'.replace('\n', '\\n')