前言
HTTP實現文件下載時,只要在服務器設置好相關響應頭,並使用二進制傳輸文件數據即可,而客戶端(浏覽器)會根據響應頭接收文件數據。而在Node.js中,設置好響應頭後,讀取文件流,再使用“.pipe()”方法將流轉接到響應對象Response就可以實現一個簡單的文件下載服務器。
1. 文件下載介紹
HTTP基於請求頭和響應頭實現狀態交互,在得到服務器正確響應狀態後,而客戶端首先會解析響應頭,並根據響應頭來接收和展示數據(響應體)。對於文件下載來說,其實現過程如下:
1.客戶端發起文件資源請求
2.服務器查找對應文件,並設置”Content-Type”、”Content-Disposition”等響應頭,分別用於表示文件的”MIME”類型及文件描述
3.客戶端根據服務器返回的響應頭解析和接收文件數據
需要設置的響應頭
設置文件下載響應頭時,除了常用的HTTP響應頭外,比較重要是還要設置以下兩個響應頭:
Content-Type: application/octet-stream Content-Disposition: attachment; filename=MyFileName.ext
在上面的設置中,”Content-Type: application/octet-stream”告訴浏覽器這是一個二進制文件,”Content-Disposition”告訴浏覽器這是一個需要下載的附件並告訴浏覽器默認的文件名。如果不添加”Content-Disposition”響應頭,浏覽器可能會下載或顯示文件內容,不同浏覽器的處理有所不同。
2. Node.js文件下載服務器實現
接下來我們基於Express 框架實現一個簡單文件下載服務器,在這個服務器中主要包括兩個功能:服務器文件的浏覽、文件的下載。
2.1 添加路由
創建Express應用後,添加如下兩個路由:
router.get('/files', function(req, res, next) {
// 顯示服務器文件
});
router.get('/file/:fileName', function(req, res, next) {
// 實現文件下載
});
上面的添加的兩個路由分別用於:顯示服務器文件、實現文件下載。
2.2 顯示服務器文件
實現服務器文件的顯示,要通過”fs”模塊讀取文件目錄並進行文件/目錄檢查等。還需要使用”path”模塊處理文件路徑。首先引入這兩個模塊:
const fs = require('fs');
const path = require('path');
顯示服務器文件實現代碼如下:
router.get('/files', function(req, res, next) {
// 顯示服務器文件
// 文件目錄
var filePath = path.join(__dirname, './');
fs.readdir(filePath, function(err, results){
if(err) throw err;
if(results.length>0) {
var files = [];
results.forEach(function(file){
if(fs.statSync(path.join(filePath, file)).isFile()){
files.push(file);
}
})
res.render('files', {files:files});
} else {
res.end('當前目錄下沒有文件');
}
});
});
上面代碼中,讀取目錄後通過視圖文件”files.ejs”顯示可下載文件列表。其代碼如下:
<!DOCTYPE html>
<html>
<head>
<title>下載文件選擇</title>
</head>
<body>
<h1>請選擇下載文件:</h1>
<% if(files.length>0) {%>
<ul>
<% files.forEach(function(file){ %>
<li>
<a href="/file/<%- file %>" target="_blank"><%- file %></a>
</li>
<%})%>
</ul>
<%} else {%>
<p>沒有可下載文件…</p>
<%}%>
</body>
</html>
2.3 實現文件下載
實現文件下載時,可以先讀取文件到一個”Buffer”中,再通過”res.send()”或”res.end()”方法發送文件數據,也可以基於流(”Stream”)實現文件數據的發送。使用”Stream”實現文件下載時,可以使用”fs.createReadStream()”方法創建一個可讀流,而響應對象Response是一個可寫流。這樣,只需要通過”.pipe()”方法將文件流轉接到Response響應流中即可。
文件下載實現代碼如下:
router.get('/file/:fileName', function(req, res, next) {
// 實現文件下載
var fileName = req.params.fileName;
var filePath = path.join(__dirname, fileName);
var stats = fs.statSync(filePath);
if(stats.isFile()){
res.set({
'Content-Type': 'application/octet-stream',
'Content-Disposition': 'attachment; filename='+fileName,
'Content-Length': stats.size
});
fs.createReadStream(filePath).pipe(res);
} else {
res.end(404);
}
});
總結
以上就是利用Node.js實現HTTP文件下載的全部內容,希望對大家學習Node.js有所幫助。