<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                - server - 思路 - 示例 - client - 測試 [TOC] ## server ### 思路 斷點續傳的服務器主要是要注意一個請求頭——`Range`,嗯,在node里接收是這樣的 ``` let range = req.headers['range']; <<< bytes = 0-999 ``` 其中`bytes = 0-999`即是`Range`的值,于是乎我們就能利用整個值來控制讀取的`start`和`end`。 >[info]值得注意的是,客戶端請求的這個range僅僅只是一個口頭要求,并不具備任何實質性的影響力,要怎么返回數據給客戶端還是服務端說了算,so究竟從什么數字編碼開始才是一個資源文件開始的索引位置?嗯,只要服務器愿意,可以是0也可以是1甚至可以是10086。 拿到range后,我們就可以將range中的`x-x`和我們`createStream`的`start/end`形成映射,從而達到控制輸出的目的。 ``` fs.createReadStream(p, { start, end }).pipe(res); ``` >[danger] **注意:** createStream API 的索引位置是包前又包后的。 另外還有一點需要注意的是我們要返回給客戶端兩個頭 - `Accept-Ranges:bytes` 表明服務器是否支持指定范圍請求及哪種類型的分段請求 - `Content-Range:bytes start-end/total`: 告訴他這次我們返回的數據是哪里到哪里的,數據總共有多少字節,這樣客戶端才能知道下次該從哪里請求數據,是否已經拿完數據該結束請求了。 #### 關于索引位置協商 介于創建可寫可讀流指定索引時是包前又包后的, 個人推設置 `薦Range:bytes=start-end`時候,第一個字節因以1開始,并且請求的數據要包括end(即要包后),然后我們在服務器端用`fs.createReadStream()`設置rs的start和end時候統一將從請求頭獲取的Range中的start和end減一。 ``` >>> Range:bytes=1-9 ... let range = req.headers['range']; let result = range.match(/bytes=(\d*)-(\d*)/); let start = result[0]; let end = result[1]; ... res.setHeader('Accept-Range','bytes'); res.setHeader('Content-Range',`bytes ${start}-${end}/${statObj.size}`) //1-9/total res.statusCode = 206; ... fs.createReadStream(filepath,{ start:start-1,end:end-1 //0-8 }); ... >>> Range:bytes=10-18 >>> ... ``` ### 示例 ``` let http = require('http'); let fs = require('fs'); let path = require('path'); let { promisify } = require('util'); let stat = promisify(fs.stat); let server = http.createServer(async function (req, res) { let p = path.join(__dirname, 'content.txt'); let statObj = await stat(p); let total = statObj.size; let start = 0; let end = total; let range = req.headers['range']; if (range) { res.setHeader('Accept-Ranges','bytes'); let result = range.match(/bytes=(\d*)-(\d*)/); start = result[1]?parseInt(result[1]):start; end = result[2]?parseInt(result[2]):end; res.setHeader('Content-Range',`bytes ${start}-${end}/${total}`) } res.setHeader('Content-Type', 'text/plain;charset=utf8'); // res.write('輸出開始'); fs.createReadStream(p, { start, end }).pipe(res); }); server.listen(8080); ``` ## client 知道了服務端是怎么控制輸出的,客戶端就簡直了~ 要不,我們就直接上代碼? ``` ... let options = { hostname:'localhost', port:8080, path:'/', method:'GET' } let ws = fs.createWriteStream('./download.txt'); let pause = false; let start = 0; let speed = 10; let end = start+speed; download(); process.stdin.on('data',function(chunk){ chunk = chunk.toString(); if(chunk.includes('p')){ pause = true }else{ pause = false; download(); } }); //--- --- --- function download(){ options.headers = { Range:`bytes=${start}-${end}` //請求頭看這里 } http.get(options,function(res){ let range = res.headers['content-range']; let total = range.split('/')[1]; let buffers = []; res.on('data',function(chunk){ buffers.push(chunk); }); res.on('end',function(){ ws.write(Buffer.concat(buffers)); setTimeout(function(){ if(pause === false&&start<total){ start+=end+1; nextEnd = end+10; end = nextEnd+1<total?nextEnd:total; download(); } },1000) }) }) } ``` 以上實現了一個支持暫停下載的斷點續傳demo, 唯一要稍微注意一點的是,我們是通過`Range:Bytes=x-xx`這頭來控制下載的。 ## 測試 ``` curl -v -H 'Range:bytes=0-9' http://localhost:8080 //本文中的栗子請求的數據索引是包前又包后的 ``` --- End
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看