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的作用,其實很多東西都可以通過請求頭和響應頭來操作,只是目前太菜了 好多還只能看看….