2017-08-28 75 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

相關問題