MST
星途 面试题库

面试题:Node.js文件下载时如何实现断点续传

在Node.js实现文件下载功能中,要求实现断点续传。请阐述断点续传的原理,并基于Express框架编写代码实现该功能,同时说明需要处理哪些HTTP头信息。
12.1万 热度难度
前端开发Node.js

知识考点

AI 面试

面试题答案

一键面试

断点续传原理

断点续传主要基于HTTP协议中的Range头和Content-Range头。客户端通过Range头告诉服务器需要下载文件的哪一部分,格式为Range: bytes=start-end,其中start是起始字节位置,end是结束字节位置(可选,如果不指定则表示到文件末尾)。服务器接收到带有Range头的请求后,会根据该头信息计算出要返回的文件部分,并通过Content-Range头告知客户端返回数据在整个文件中的范围,格式为Content-Range: bytes start-end/total,其中total是文件的总字节数。如果服务器支持断点续传,会返回206 Partial Content状态码,否则返回416 Requested Range Not Satisfiable状态码。

基于Express框架实现代码

const express = require('express');
const fs = require('fs');
const path = require('path');
const app = express();
const port = 3000;

app.get('/download', (req, res) => {
    const filePath = path.join(__dirname, 'yourFile.pdf');
    const stat = fs.statSync(filePath);
    const fileSize = stat.size;
    const range = req.headers.range;
    if (range) {
        const parts = range.replace(/bytes=/, '').split('-');
        const start = parseInt(parts[0], 10);
        const end = parts[1] ? parseInt(parts[1], 10) : fileSize - 1;
        const chunksize = (end - start) + 1;
        const file = fs.createReadStream(filePath, { start, end });
        const head = {
            'Content-Range': `bytes ${start}-${end}/${fileSize}`,
            'Accept-Ranges': 'bytes',
            'Content-Length': chunksize,
            'Content-Type': 'application/pdf'
        };
        res.writeHead(206, head);
        file.pipe(res);
    } else {
        const head = {
            'Content-Length': fileSize,
            'Content-Type': 'application/pdf'
        };
        res.writeHead(200, head);
        fs.createReadStream(filePath).pipe(res);
    }
});

app.listen(port, () => {
    console.log(`Server running on port ${port}`);
});

需要处理的HTTP头信息

  1. Range:客户端发送,告知服务器需要下载文件的字节范围。
  2. Content-Range:服务器发送,告知客户端返回数据在整个文件中的字节范围。
  3. Accept-Ranges:服务器发送,告知客户端服务器支持按字节范围请求数据,值通常为bytes
  4. Content-Length:对于普通下载(无Range头),服务器发送文件的总大小;对于断点续传(有Range头),服务器发送本次返回数据的大小。