myfreax

Node.js如何实现断点续传

Node.js如何实现断点续传

2 min read
By myfreax
Node.js如何实现断点续传

Range 是一个请求首部,告知服务器返回文件的哪一部分。在一个  Range 首部中,可以一次性请求多个部分,服务器会以 multipart 文件的形式将其返回。如果服务器返回的是范围响应,需要使用 206Partial Content 状态码。假如所请求的范围不合法,那么服务器会返回  416Range Not Satisfiable 状态码,表示客户端错误。服务器允许忽略  Range  首部,从而返回整个文件,状态码用 200

安装node-fetch

npm install node-fetch

实现断点续传

ctrl = new AbortController()
signal = ctrl.signal
url = 'https://images.pexels.com/photos/45201/kitty-cat-kitten-pet-45201.jpeg?d='+Date.now()
res = await fetch(url, { signal })
acceptRanges = res.headers.get('accept-ranges') === 'bytes'
contentLength = parseInt(res.headers.get('content-length'))
chunks = []
downloaded = 0

res.body.pipeTo(new WritableStream({
  write(chunk) {
    chunks.push(chunk) // uint8array
    downloaded += chunk.byteLength
    console.log(downloaded, contentLength)
    ctrl.abort()
    console.log(URL.createObjectURL(new Blob(chunks, {type:'image/jpeg'})))
    resumePartialRequest(url, downloaded)
  }
}))

async function resumePartialRequest (url, start = 0, end = '') {
  const res = await fetch(url, {
    headers: {
      'range': `bytes=${start}-${end}` 
    }
  })
  await res.body.pipeTo(new WritableStream({
    write(chunk) {
      chunks.push(chunk)
      downloaded += chunk.byteLength
      console.log(downloaded, contentLength)
    }
  }))
  console.log(URL.createObjectURL(new Blob(chunks, {type:'image/jpeg'})))
}

基于HTTP的实现

Range - HTTP | MDN
The Range 是一个请求首部,告知服务器返回文件的哪一部分。在一个 Range 首部中,可以一次性请求多个部分,服务器会以 multipart 文件的形式将其返回。如果服务器返回的是范围响应,需要使用 206 Partial Content 状态码。假如所请求的范围不合法,那么服务器会返回 416 Range Not Satisfiable 状态码,表示客户端错误。服务器允许忽略 Range 首部,从而返回整个文件,状态码用 200 。