- 前端部分在vue中直接使用video标签
<video src="http://localhost:3000/lweb/videoPlaySplit.do" controls="controls"></video>
- 后端部分使用nodejs获取文件流,进行分段处理,通过请求头的Range参数返回文件流的部分数据,实现大文件视频的分段传输、边下边播
videoPlaySplit(req, body, res, next) { let path = '/test.mp4'; // 获取文件信息 let stat = fs.statSync(path); let fileSize = stat.size; let range = req.headers.range; if (range) { //请求体包含range头,返回206状态码 let parts = range.replace(/bytes=/, "").split("-"); let start = parseInt(parts[0], 10); // 分段流大小1Mb let splitSize = 1 * 1024 * 1024; // 如果请求头range中有尾坐标,取该坐标,否则请求指定大小 let end = parts[1] ? parseInt(parts[1], 10) : start + splitSize; // end 在最后取值为 fileSize - 1 end = end > fileSize - 1 ? fileSize - 1 : end; let chunksize = end - start + 1; // 获取该范围内的分段流 let file = fs.createReadStream(path, { start, end }); let head = { "Content-Range": `bytes ${start}-${end}/${fileSize}`, "Accept-Ranges": "bytes", "Content-Length": chunksize, "Content-Type": "video/mp4", }; res.writeHead(206, head); file.pipe(res); } else { //请求体不包含range头,返回200状态码,并直接返回整个流文件(大文件需要加载完才能播放) let head = { "Content-Length": fileSize, "Content-Type": "video/mp4", }; res.writeHead(200, head); fs.createReadStream(path).pipe(res); } }
HTTP/1.1 206状态码表示的是:客户端通过发送范围请求头Range获取资源的部分数据。这种请求可以将服务端文件分割成多个部分传给客户端,可用于解决网络问题以及大文件下载问题。对于一个很大的视频,就可以采用这种请求将视频流分成多个部分下载。通过这种分段流传输的方式,无需全部下载即可对视频进行播放,同时也支持播放时修改播放进度。