基於node如何實作http傳輸大檔案?以下這篇文章為大家介紹幾個基於nodejs的幾種http檔案傳輸實作方案,希望對大家有幫助!
基於nodejs的http檔傳輸方案在現階段的前後端全端開發中有都很重要的作用,本文我將透過幾種方案實現http傳輸大檔案。在實作功能之前,我們先透過nodejs的fs模組寫入一個大文件,並在專案中產生一個本地文件:
const fs = require('fs'); const writeStream = fs.createWriteStream(__dirname + "/file.txt"); for(let i = 0;i <= 100000; i++) { writeStream.write(`${i} —— 我是${i}号文件\n`, "utf-8"); } writeStream.end();
以上程式碼成功運行後,在目前的執行目錄下將會產生一個大小為 3.2MB 大小的文字文件,該文件將作為下列方案的「大檔案素材」。在列出大檔案傳輸方案之前,我們先封裝後面即將使用的兩個公共方法: 檔案讀取方法
和檔案壓縮方法
:
// 封装读取文件的方法 const readFile = async (paramsData) => { return new Promise((resolve, reject) => { fs.readFile(paramsData, (err, data) => { if(err) { reject('文件读取错误'); } else { resolve(data); } }) }) } // 封装文件压缩方法 const gzip = async (paramsData) => { return new Promise((resolve, reject) => { zlib.gzip(paramsData, (err, result) => { if(err) { reject('文件压缩错误'); } else { resolve(result); } }) }) }
1. 透過大檔案在資料壓縮後傳送
瀏覽器在發送請求時,都會攜帶 accept
和 accept- *
請求標頭訊息,用於告訴伺服器目前瀏覽器支援的檔案類型、支援的壓縮格式清單和支援的語言。請求頭中的 Accept-Encoding
字段,用於將客戶端能夠理解的內容編碼方式(通常是某種壓縮演算法)告訴給服務端。服務端會選擇一個客戶端所支援的方式,並透過回應頭 Content-Encoding
來通知客戶端該選擇,回應頭告訴瀏覽器回傳的JS 腳本,是經過 gzip
壓縮演算法處理過的
// 请求头 accept-encoding: gzip, deflate, br
// 响应头 cache-control: max-age=2592000 content-encoding: gzip content-type: application/x-javascript
基於 Accept-Encoding
和 Content-Encoding
字段的了解,我們來驗證一下未開啟 gzip
#和開啟 gzip
的效果。
// 实现一个简单的文件读取服务器(没有开启gzip) const server = http.createServer(async (req, res) => { res.writeHead(200, { "Content-Type": "text/plain;charset=utf-8", }); const buffer = await readFile(__dirname + '/file.txt'); res.write(buffer); res.end(); }) server.listen(3000, () => { console.log(`server启动成功`) })
// 实现一个简单的文件读取服务器(开启gzip) const server = http.createServer(async(req, res) => { res.writeHead(200, { "Content-Type": "text/plain;charset=utf-8", "Content-Encoding": "gzip" }); const buffer = await readFile(__dirname + '/file.txt'); const gzipData = await gzip(buffer); res.write(gzipData); res.end(); }) server.listen(3000, () => { console.log(`server启动成功`) })
#2. 透過資料分塊傳輸
有場景需要用從資料庫中查詢獲得的資料產生一個大的HTML 表格的時候,或者需要傳輸大量的圖片的時候,可以透過分塊傳輸實現。
Transfer-Encoding: chunked Transfer-Encoding: gzip, chunked
回應頭 Transfer-Encoding
欄位的值為 chunked
,表示資料以一系列分塊的形式進行傳送。要注意的是 Transfer-Encoding
和 Content-Length
這兩個欄位是互斥的,也就是說回應封包中這兩個欄位不能同時出現。
// 数据分块传输 const spilitChunks = async () =>{ const buffer = await readFile(__dirname + '/file.txt'); const lines = buffer.toString('utf-8').split('\n'); let [chunks, i, n] = [[], 0, lines.length]; while(i < n) { chunks.push(lines.slice(i, i+= 10)); }; return chunks; } const server = http.createServer(async(req, res) => { res.writeHead(200, { "Content-Type": "text/plain;charset=utf-8", "Transfer-Encoding": "chunked", "Access-Control-Allow-Origin": "*", }); const chunks = await spilitChunks(); for(let i =0; i< chunks.length; i++) { setTimeout(() => { let content = chunks[i].join("&"); res.write(`${content.length.toString(16)}\r\n${content}\r\n`); }, i * 1000); } setTimeout(() => { res.end(); }, chunks.length * 1000); }) server.listen(3000, () => { console.log(`server启动成功`) })
3. 透過資料流的形式傳輸
#當使用 Node.js
向客戶端傳回大文件時,使用流的形式來返回文件流能避免處理大文件時,佔用過多的記憶體。具體實作方式如下圖所示。當使用流的形式來傳回檔案資料時,HTTP 回應頭 Transfer-Encoding
欄位的值為 chunked
,表示資料以一系列分塊的形式進行傳送。
const server = http.createServer((req, res) => { res.writeHead(200, { "Content-Type": "text/plain;charset=utf-8", "Content-Encoding": "gzip", "Transfer-Encoding": "chunked" }); fs.createReadStream(__dirname + "/file.txt") .setEncoding("utf-8") .pipe(zlib.createGzip()) .pipe(res); }) server.listen(3000, () => { console.log(`server启动成功`) })
更多node相關知識,請造訪:nodejs 教學! !
以上是基於nodejs如何實作http傳輸大檔案? (實踐方法分享)的詳細內容。更多資訊請關注PHP中文網其他相關文章!