2017-08-28 105 views
3

我想将内存中的数据打包到文本文件中并将其发送给用户,从而触发文件下载。Node Express.js - 从内存中下载文件 - '文件名必须是字符串'

我有以下代码:

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

}); 

它不断抛出一个错误,指出内容处置的文件名参数必须是一个字符串。 fileName肯定是一个字符串,所以我不知道发生了什么。

+0

哪一行给出错误? –

+0

请用'let'声明你的局部变量,如'fileType','fileName'和'fileData'。在服务器中使用偶然的全局变量是一种灾难。 – jfriend00

+0

如果你看[res.download()']代码(https://github.com/expressjs/express/blob/master/lib/response.js#L514),你可以看到它只是调用'res.sendFile()'所以它只能用来从文件中发送数据,而不是从内存中发送数据。您将不得不寻找一种不同的方式直接从内存发送或首先写入临时文件。 – jfriend00

回答

3

更新:

感谢@ jfriend00的建议,这是更好,更有效地直接发送缓冲区,以客户为文件,而不是在服务器磁盘先保存它。

实现,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); 
}); 

根据快递documentres.download() API是:

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

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

请注意res.download()的第一个参数是一个“路径”,它表示将要下载的服务器中的文件路径。在你的代码中,第一个参数是一个Buffer,这就是为什么Node.js会抱怨“filename参数必须是一个字符串” - 默认情况下,Content-Disposition头文件“filename =”参数是路径

要使用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])

+0

在没有首先将数据写入文件的情况下,应该有办法解决这个问题。此外,您的代码不会生成与其他请求不冲突的唯一文件名,也不会在适当的时间清理临时文件。 – jfriend00

+0

@ jfriend00你是对的。将数据写入文件并最终将其删除效率不高。我正在寻找更好的解决方案,有什么建议吗? – shaochuancs

+0

@ jfriend00我发现了一个更好的解决方案,它不需要保存文件服务器。感谢您的建议。 – shaochuancs

相关问题