• <fieldset id="8imwq"><menu id="8imwq"></menu></fieldset>
  • <bdo id="8imwq"><input id="8imwq"></input></bdo>
    最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
    問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
    當前位置: 首頁 - 科技 - 知識百科 - 正文

    NodeJS使用Range請求實現下載功能的方法示例

    來源:懂視網 責編:小采 時間:2020-11-27 22:06:24
    文檔

    NodeJS使用Range請求實現下載功能的方法示例

    NodeJS使用Range請求實現下載功能的方法示例:前言 本篇使用 NodeJS 的 HTTP 服務創建客戶端,使用 Range 請求實現下載功能,并通過本篇的 Demo 擴展在業務中實現斷點續傳等功能的思路。 服務端的實現 我們通過 http 模塊創建服務器處理 Range 請求,在服務器代碼中我們為了減少回調嵌套使用 asyn
    推薦度:
    導讀NodeJS使用Range請求實現下載功能的方法示例:前言 本篇使用 NodeJS 的 HTTP 服務創建客戶端,使用 Range 請求實現下載功能,并通過本篇的 Demo 擴展在業務中實現斷點續傳等功能的思路。 服務端的實現 我們通過 http 模塊創建服務器處理 Range 請求,在服務器代碼中我們為了減少回調嵌套使用 asyn

    前言

    本篇使用 NodeJS 的 HTTP 服務創建客戶端,使用 Range 請求實現下載功能,并通過本篇的 Demo 擴展在業務中實現斷點續傳等功能的思路。

    服務端的實現

    我們通過 http 模塊創建服務器處理 Range 請求,在服務器代碼中我們為了減少回調嵌套使用 async 函數,所以需要將異步的操作方法轉換成 Promise,以往我們使用 util 的 promisify 來一個一個轉換異步方法,比較麻煩,我們這次使用第三方模塊 mz 并直接引入轉換好的替代模塊。

    使用 mz 之前需要先安裝:

    npm install mz

    服務端代碼如下:

    // 文件:server.js
    const http = require("http");
    const path = require("path");
    const url = require("url");
    
    // 引入 mz 模塊轉換成 Promise 的 fs 模塊
    const fs = require("mz/fs");
    
    // 請求處理函數
    async function listener(req, res) {
     // 獲取 range 請求頭,格式為 Range:bytes=0-5
     let range = req.headers["range"];
    
     // 下載文件路徑
     let p = path.resovle(__dirname, url.parse(url, true).pathname);
    
     // 存在 range 請求頭將返回范圍請求的數據
     if (range) {
     // 獲取范圍請求的開始和結束位置
     let [, start, end] = range.match(/(\d*)-(\d*)/);
    
     // 錯誤處理
     try {
     let statObj = await fs.stat(p);
     } catch (e) {
     res.end("Not Found");
     }
    
     // 文件總字節數
     let total = statObj.size;
    
     // 處理請求頭中范圍參數不傳的問題
     start = start ? ParseInt(start) : 0;
     end = end ? ParseInt(end) : total - 1;
    
     // 響應客戶端
     res.statusCode = 206;
     res.setHeader("Accept-Ranges", "bytes");
     res.setHeader("Content-Range", `bytes ${start}-${end}/${total}`);
     fs.createReadStream(p, { start, end }).pipe(res);
     } else {
     // 沒有 range 請求頭時將整個文件內容返回給客戶端
     fs.createReadStream(p).pipe(res);
     }
    }
    
    // 創建服務器
    const server = http.createServer(listener);
    
    // 監聽端口
    server.listen(3000, () => {
     console.log("server start 3000");
    });
    
    

    在上面服務端的代碼中,需要兼容 Range 請求和普通請求,兩種請求的區別是,如果客戶端發送的是 Range 請求,會攜帶 Range:bytes=0-5 格式的請求頭,我們可以通過 req 的 headers 屬性獲取,在獲取請求頭時,原本大寫字母開頭 NodeJS 統一處理成小寫,所以獲取時應小寫。

    如果是 Range 請求則通過可讀流讀取對應的內容返回客戶端,如果不是,則通過可讀流讀取整個文件返回客戶端,在響應 Range 請求的過程中需要設置響應狀態為 206,需要設置響應頭 Accept-Ranges 值為 bytes,需要設置響應頭 Content-Range 值為 byte 0-5/100 的格式,0 為返回數據開始的索引,5 為結束的索引(包含),100 為文件的總字節數。

    在通過 url 和 path 模塊解析和拼接下載文件路徑時,應該進行錯誤檢測,如果文件不存在則直接返回客戶端 Not Found。

    我們可以使用 curl 命令來檢測我們的服務端代碼,在命令行工具中輸入下面命令,在命令窗口查看返回值是否正確。

    curl -v --header "Range:bytes=0-5" http://localhost:3000

    客戶端的實現

    在上面使用 curl 命令來訪問我們的服務器時,只能請求固定范圍的數據,而不是類似于下載功能,每次都下載一個范圍的數據,但是想要多次下載并自動維護 Range 的范圍需要借助我們自己實現的客戶端邏輯。

    為了簡便,我們的下載客戶端是在命令行窗口運行的,通過指令來模擬實際項目中的開始下載、暫停和恢復按鈕,當在窗口中輸入 s 指令時開始下載,輸入 p 指令時暫停下載,輸入 r 指令時恢復下載。

    // 文件:client.js
    const http = require("http");
    const fs = require("fs");
    const path = require("path");
    
    // 請求配置
    let config = {
     host: "localhost",
     port: 3000,
     path: "/download.txt"
    };
    
    let start = 0; // 請求初始值
    let step = 5; // 每次請求字符個數
    let pause = false; // 暫停狀態
    let total; // 文件總長度
    
    // 創建可寫流
    let ws = fs.createWriteStream(path.resolve(__dirname, config.path.slice(1)));
    
    // 下載函數
    function download() {
     // 配置,每次范圍請求 step 個字節
     config.headers = {
     "Range": `bytes=${start}-${start + step - 1}`;
     };
    
     // 維護下次 start 的值
     start += step;
    
     // 發送請求
     http.request(config, res => {
     // 獲取文件總長度
     if (typeof total !== "number") {
     total = res.headers["content-ranges"].match(/\/(\d*)/)[1];
    
     }
    
     // 讀取返回數據
     let buffers = [];
     res.on("data", data => buffers.push(data));
     res.on("end", () => {
     // 合并數據并寫入文件
     let buf = Buffer.concat(buffers);
     ws.write(buf);
    
     // 遞歸進行下一次請求
     if (!pause && start < total) {
     download();
     }
     });
     }).end();
    }
    
    // 監控輸入
    process.stdin.on("data", data => {
     // 獲取指令
     let ins = data.toString().match(/(\w*)\/r/)[1];
     switch (ins) {
     case "s":
     case "r":
     pause = false;
     download();
     break;
     case "p":
     pause = true;
     break;
     }
    });

    在上面代碼中下載的文件通過 config 中的 path 屬性配置,每次調用 download 函數下載時都會重新計算當前范圍請求的初始位置和結束位置,并設置 Range 請求頭,下一次請求靠遞歸 download 來實現。

    在執行時需先啟動我們的服務器,在通過命令行輸入 node client.js 來啟動客戶端,在命令窗口輸入對應的指令進行開始下載、暫停下載和恢復下載操作。

    總結

    相信現在已經了解什么是范圍請求,范圍請求客戶端和服務端需要做些什么,其實說白了就是對應的請求頭和響應頭的使用,需要注意的是范圍請求的響應狀態碼為 206,這樣的需求在一些上傳、下載資源的網站也很常見,其目的就是為了讓我們實現斷點續傳,不至于一次沒有上傳或下載完成的資源文件,在下一次的做同樣操作時需要重新來過,可以接著上次的位置繼續,范圍請求在視頻網站上也廣泛應用,邊請求邊觀看,不至于一次加載整個視頻資源,節省流量,節省時間。

    聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

    文檔

    NodeJS使用Range請求實現下載功能的方法示例

    NodeJS使用Range請求實現下載功能的方法示例:前言 本篇使用 NodeJS 的 HTTP 服務創建客戶端,使用 Range 請求實現下載功能,并通過本篇的 Demo 擴展在業務中實現斷點續傳等功能的思路。 服務端的實現 我們通過 http 模塊創建服務器處理 Range 請求,在服務器代碼中我們為了減少回調嵌套使用 asyn
    推薦度:
    標簽: 下載 請求 js
    • 熱門焦點

    最新推薦

    猜你喜歡

    熱門推薦

    專題
    Top
    主站蜘蛛池模板: 精品无码人妻久久久久久| 亚洲精品WWW久久久久久| 免费国产在线精品一区| 成人精品一区二区三区中文字幕| 白浆都出来了视频国产精品| 亚洲国产精品久久久久久| 无码人妻精品一区二区三区在线 | 狼色精品人妻在线视频| 国产这里有精品| 国产在视频线精品视频二代| 久久久久99精品成人片直播| 亚洲日韩精品一区二区三区| 欧美在线精品一区二区三区| 国产精品成人免费观看| 亚洲第一精品在线视频| 国产精品多p对白交换绿帽| 99久久精品国产一区二区三区| 国产精品日本一区二区不卡视频 | 国产精品超碰12396| 国产精品亚洲片在线| 亚洲а∨天堂久久精品| 国产欧美精品专区一区二区| 国产精品免费网站| 精品亚洲国产成AV人片传媒| 亚洲国产精品丝袜在线观看| 国产精品久久久久久久午夜片| 99精品久久精品| 日韩精品久久久肉伦网站| 四虎国产精品成人| 精品欧美激情在线看| 青青草原综合久久大伊人精品| 国产精品一久久香蕉国产线看观看| 最新欧美性爱精品一区二区三区| 国产精品第1页| 91精品国产成人网在线观看| CAOPORM国产精品视频免费| 人妻少妇精品视频一区二区三区| 亚洲国产精品日韩专区AV| 欧美精品一区二区三区免费观看| 国内精品伊人久久久久影院对白 | 国产精品美女久久久久AV福利|