HTTP之斷點續傳教程

這裡主要是理解http斷點續傳的原理,如何通過http請求頭操作,以及相應的請求和響應頭的設定。

server端實現

// 斷點續傳

// 客戶端要發一個頭 Range:bytes = 0 -1

// 服務端返回一個頭

// Accept-Ranges:bytes

// COntent-Ranges: 0-10/總大小

const http = require('http')

const fs = require('fs')

const path = require('path')

const {promisify} = require('util')

const stat = promisify(fs.stat) // 將方法promise化

const server = http.createServer(async (req, res) => {

// 拼接檔案路徑,讀取檔案大小

let p = path.join(__dirname, 'content.txt')

let statObj = await stat(p)

let start = 0

let end = statObj.size //可讀流是包前包後

let total = end

// 讀取檔案大小

// 讀取請求頭

let range = req.headers['range']

// 如果有請求頭部,則進行分片讀取

if (range) {

// 設定請求頭,告訴瀏覽器支援分片下載

res.setHeader('Accept-Ranges', 'bytes')

// 拿到起始位置和結束為止

let result = range.match(/bytes=(/d*)-(/d*)/)

start = result[1] ? result[1] - 0 : start

end = result[2] ? result[2] - 1 : end

// 獲取成功 並且檔案總大小告訴客戶端

res.setHeader('Content-Range', `${start}-${end}/${total}`)

}

res.setHeader('Content-Type', 'text/plain;charset=utf8');

fs.createReadStream(p, {start, end}).pipe(res)

})

server.listen(3000)

// server啟動成功

server.on('listening', () => {

console.log('http啟動完成')

})

// 關閉HTTP伺服器

server.on('close', () => {

console.log('伺服器關閉')

})

// 伺服器監聽錯誤

server.on('error', e => {

console.log(e)

})

模擬客戶端

這裡使用node模擬客戶端

const http = require('http')

const fs = require('fs')

const path = require('path')

let ws = fs.createWriteStream(path.join(__dirname, './download.txt'))

let pause = false

let start = 0

let step = 10

// 請求引數

let options = {

hostname: 'localhost',

port: 3000,

path: '/',

methods: 'GET'

}

/**

* @description 下載檔案

*/

function download () {

// 跟新請求頭

options.headers = {

Range: `bytes=${start}-${start step}`

}

// 更新下標

start = step

// 傳送請求

http.get(options, res => {

let range = res.headers['content-range']

let total = range.split('/')[0]

let buffers = []

res.on('data', chunk => {

buffers.push(chunk)

})

// 合併檔案 並寫入本地磁碟

res.on('end', () => {

ws.write(Buffer.concat(buffers))

console.log('end', buffers.toString())

// 如果不是暫停,並且沒有大於檔案總長度,才會繼續下載

// if (pause === false && start < total) download()

// 為了展示效果,這裡做一個手動延遲

setTimeout(() => {

if (pause === false && start < total) download()

}, 5000)

})

})

}

download()

// 下載 每次獲取10個 我們在控制檯進行操作 輸入p是暫停,其他任意鍵是繼續

process.stdin.on('data', chunk => {

chunk = chunk.toString()

if (chunk.includes('p')) {

pause = true

} else {

pause = false

download()

}

})

總結

通過以上簡單的程式碼,對斷點續傳,以及http請求頭做了一個學習和體會,知道了Accept-Range的作用,其實很多東西都可以通過請求頭和響應頭來操作,只是目前太菜了 好多還只能看看….