前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
  • HTTP

    • 基础篇

      • HTTP的前世今生
      • HTTP是什么
      • HTTP世界全览
      • HTTP分层
      • 键入网址到回车发生什么
      • HTTP报文是什么样子的
      • 理解请求方法
      • URI
      • 响应状态码
      • HTTP有哪些特点
      • HTTP优缺点
      • HTTP的实体数据
      • HTTP传输大文件
      • HTTP的连接管理
      • HTTP的重定向
      • HTTP的Cookie机制
      • HTTP的缓存控制
      • HTTP的代理服务
      • HTTP的缓存代理
    • 高级篇

    • 扩展篇

  • 浏览器相关

  • 计算机基础

# HTTP传输大文件

30 秒速记

  • 四招:压缩(变小)、分块传输(边生成边发)、范围请求(只要一段)、多段范围(一次要几段)
  • 压缩:Accept-Encoding / Content-Encoding,只对文本有效,图片视频压不动
  • 分块:Transfer-Encoding: chunked,长度未知也能发,不能和 Content-Length 同时出现,只在 HTTP/1.1 里有
  • 范围:Range: bytes=x-y → 206 + Content-Range;越界 416;支持与否看 Accept-Ranges
  • 多段:multipart/byteranges + boundary 分隔;几招可以组合,解决的是不同问题

HTTP 传大文件有四招,按问题选:内容能压就先压,长度不知道就分块发,只要一部分就用范围请求。 压缩针对文本,HTML、JS 压完能小一大半,图片视频本身已经压过,再压没意义。分块传输是服务器不用等内容全部生成好,生成一块发一块,内存压力小,流式渲染、导出报表常用。范围请求是客户端说「我只要第 1000 到 1999 字节」,视频拖进度条、断点续传都靠它。这几招不互斥,比如动态生成的文本可以压缩后再分块发。

四种手段对照着记最清楚:

手段 解决什么 关键头 状态码
压缩 数据太大 Accept-Encoding / Content-Encoding 200
分块传输 长度未知、要边生成边发 Transfer-Encoding: chunked 200
范围请求 只要其中一段 Range / Content-Range / Accept-Ranges 206 / 416
多段范围 一次要好几段 Content-Type: multipart/byteranges; boundary=... 206

前端日常最常见的几个场景:

  • 静态资源(JS、CSS、HTML):构建时预压缩成 .br / .gz,Nginx 按 Accept-Encoding 直接返回,省掉实时压缩的 CPU。
  • 流式 SSR:React 18 的 renderToPipeableStream、Next.js 的流式渲染,在 HTTP/1.1 下就是靠 chunked 先把页面骨架发出去,数据好了再补后面的块。
  • 视频播放:<video> 第一次请求就会带 Range: bytes=0-,服务端返回 206 后,拖进度条时浏览器会按新位置再发范围请求。
  • 大文件上传:方向反过来,前端用 file.slice() 切片分别上传,服务端拼接。这是应用层的方案,HTTP 的 Range 只管下载。

Node 里不写 Content-Length 直接多次 res.write(),HTTP/1.1 下会自动变成 chunked:

require('http').createServer((req, res) => {
  res.write('第一块\n')                     // 立刻发出
  setTimeout(() => res.end('第二块\n'), 1000) // 1 秒后发第二块并结束
}).listen(3000)
// curl -i localhost:3000 能看到 Transfer-Encoding: chunked
@前端进阶之旅: 代码已经复制到剪贴板

面试官追问

追问 1视频页用了 chunked,用户拖到 30 分钟处还是从头加载,为什么?
参考回答

chunked 只是服务器怎么把这次响应分批发出去,客户端没法通过它指定从哪开始。拖进度条要的是范围请求,<video> 会自动发 Range,前提是服务端支持并返回 206。

追问 2要下载一个几 GB 的文件,服务端先全读进内存再返回可以吗?
参考回答

不行,几个人同时下载内存就爆了。用流式读取边读边写,Node 里就是 fs.createReadStream(file).pipe(res)。文件长度已知的话带上 Content-Length 就行,长度未知才用 chunked。

追问 3同一个静态服务既有大日志文本又有视频,统一开 gzip 可以吗?
参考回答

按类型开。文本开,Nginx 用 gzip_types 列出 text/plain、application/json、application/javascript 这些;视频、图片别加进去,压不动还白费 CPU。

追问 4怎么一眼判断一个下载地址支不支持断点续传?
参考回答

curl -I 看响应有没有 Accept-Ranges: bytes,再实际发一个 curl -r 0-99 -I 看是不是 206。只返回 200 就是不支持,下载器只能从头来。

追问 5HTTP/2 下还有 chunked 吗?
参考回答

没有了。HTTP/2 自带二进制分帧,数据天然一帧一帧地发,规范明确不允许用 Transfer-Encoding: chunked。压缩和范围请求在 HTTP/2 里照样用。

# 数据压缩

30 秒速记

  • 浏览器 Accept-Encoding: gzip, deflate, br 报能力 → 服务器挑一个压缩 → Content-Encoding 回告
  • 压缩率 50% ≈ 同带宽下传输时间减半,文本类效果最明显
  • 图片、音视频本身已高度压缩,再 gzip 基本不变小,甚至略大
  • Nginx:gzip on 默认只压 text/html,JS、CSS、JSON 要自己加进 gzip_types
  • 静态资源最好构建时预压缩(gzip_static),小于 1KB 左右的响应没必要压

数据压缩就是服务器用浏览器支持的算法把响应体压小再发,是传大文本最基础、性价比最高的优化。 浏览器在 Accept-Encoding 里列出能解的格式,服务器挑一个压缩,再用 Content-Encoding 告诉浏览器用的哪个。100KB 的 HTML 压到 30KB 很常见,相当于带宽没变网速快了好几倍。但它只对文本有效,图片视频本来就是压缩格式。实际配置时有个坑,Nginx 的 gzip on 默认只压 text/html,JS、CSS 和 JSON 接口要在 gzip_types 里手动加上,不然开了跟没开差不多。

gzip on;
gzip_min_length 1k;            # 太小的响应不压
gzip_types text/css application/javascript application/json image/svg+xml;
gzip_static on;                # 有 app.js.gz 就直接发,不用实时压缩
@前端进阶之旅: 代码已经复制到剪贴板

通常浏览器在发送请求时都会带着“Accept-Encoding”头字段,里面是浏览器支持的压缩格式列表,例如 gzip、deflate、br 等,这样服务器就可以从中选择一种压缩算法,放进“Content-Encoding”响应头里,再把原数据压缩后发给浏览器。

如果压缩率能有 50%,也就是说 100K 的数据能够压缩成 50K 的大小,那么就相当于在带宽不变的情况下网速提升了一倍,加速的效果是非常明显的。

不过这个解决方法也有个缺点,gzip 等压缩算法通常只对文本文件有较好的压缩率,而图片、音频视频等多媒体数据本身就已经是高度压缩的,再用 gzip 处理也不会变小(甚至还有可能会增大一点),所以它就失效了。

不过数据压缩在处理文本的时候效果还是很好的,所以各大网站的服务器都会使用这个手段作为“保底”。例如,在 Nginx 里就会使用“gzip on”指令,启用对“text/html”的压缩

面试官追问

追问 1给 JPEG、视频统一套一层 gzip,负责人说只要压缩就一定更小,对吗?
参考回答

不对。这些格式本身已经压缩过,熵很高,gzip 找不到可压的重复内容,结果基本一样大,加上头部开销还可能略大,CPU 白烧。SVG 例外,它是文本,压缩效果很好。

追问 2开了 gzip on,JS 文件在 Network 面板里还是没有 Content-Encoding,为什么?
参考回答

gzip_types 没包含 application/javascript,默认只压 text/html。另外检查文件是不是小于 gzip_min_length,以及前面是不是有一层代理把压缩去掉了。

追问 3旧浏览器只声明 gzip,网关固定返回 br,有什么问题?
参考回答

客户端解不开,直接白屏或报错。服务端必须在 Accept-Encoding 里出现过的格式中选,br 和 gzip 都准备着,按请求头挑。

追问 4压缩响应体变小了,但缺了 Content-Encoding,会怎样?
参考回答

浏览器把压缩字节当原文解析,页面显示乱码,JSON 直接解析失败。压缩和打标必须在同一层做,常见问题是应用压了没打头,或者网关解压了没删头。

追问 5实时压缩吃 CPU,怎么优化?
参考回答

静态资源构建时就压好,比如用 compression-webpack-plugin 产出 .gz / .br,Nginx 开 gzip_static 直接发。只有接口这类动态内容才实时压,压缩级别用中等,比如 gzip_comp_level 设 5 左右,再高收益很小。

# 分块传输

30 秒速记

  • Transfer-Encoding: chunked:响应体拆成多块依次发,接收方按顺序拼回去
  • 适合长度事先不知道的内容:流式渲染、数据库边查边出的报表、日志流
  • 每块 = 十六进制长度 + \r\n + 数据 + \r\n,长度只算数据本身
  • 以长度 0 的块结束:0\r\n\r\n;没有它客户端会一直等
  • 和
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
  • HTTP

    • 基础篇

      • HTTP的前世今生
      • HTTP是什么
      • HTTP世界全览
      • HTTP分层
      • 键入网址到回车发生什么
      • HTTP报文是什么样子的
      • 理解请求方法
      • URI
      • 响应状态码
      • HTTP有哪些特点
      • HTTP优缺点
      • HTTP的实体数据
      • HTTP传输大文件
        • 数据压缩
        • 分块传输
        • 范围请求
        • 多段数据
        • 小结
      • HTTP的连接管理
      • HTTP的重定向
      • HTTP的Cookie机制
      • HTTP的缓存控制
      • HTTP的代理服务
      • HTTP的缓存代理
    • 高级篇

    • 扩展篇

  • 浏览器相关

  • 计算机基础

完整面试题地址:
作者:程序员poetry
扫码关注作者公众号:「前端进阶之旅」 每天分享技术干货
前端进阶之旅公众号二维码

HTTP传输大文件|HTTP协议篇

# HTTP传输大文件

30 秒速记

  • 四招:压缩(变小)、分块传输(边生成边发)、范围请求(只要一段)、多段范围(一次要几段)
  • 压缩:Accept-Encoding / Content-Encoding,只对文本有效,图片视频压不动
  • 分块:Transfer-Encoding: chunked,长度未知也能发,不能和 Content-Length 同时出现,只在 HTTP/1.1 里有
  • 范围:Range: bytes=x-y → 206 + Content-Range;越界 416;支持与否看 Accept-Ranges
  • 多段:multipart/byteranges + boundary 分隔;几招可以组合,解决的是不同问题

HTTP 传大文件有四招,按问题选:内容能压就先压,长度不知道就分块发,只要一部分就用范围请求。 压缩针对文本,HTML、JS 压完能小一大半,图片视频本身已经压过,再压没意义。分块传输是服务器不用等内容全部生成好,生成一块发一块,内存压力小,流式渲染、导出报表常用。范围请求是客户端说「我只要第 1000 到 1999 字节」,视频拖进度条、断点续传都靠它。这几招不互斥,比如动态生成的文本可以压缩后再分块发。

四种手段对照着记最清楚:

手段 解决什么 关键头 状态码
压缩 数据太大 Accept-Encoding / Content-Encoding 200
分块传输 长度未知、要边生成边发 Transfer-Encoding: chunked 200
范围请求 只要其中一段 Range / Content-Range / Accept-Ranges 206 / 416
多段范围 一次要好几段 Content-Type: multipart/byteranges; boundary=... 206

前端日常最常见的几个场景:

  • 静态资源(JS、CSS、HTML):构建时预压缩成 .br / .gz,Nginx 按 Accept-Encoding 直接返回,省掉实时压缩的 CPU。
  • 流式 SSR:React 18 的 renderToPipeableStream、Next.js 的流式渲染,在 HTTP/1.1 下就是靠 chunked 先把页面骨架发出去,数据好了再补后面的块。
  • 视频播放:<video> 第一次请求就会带 Range: bytes=0-,服务端返回 206 后,拖进度条时浏览器会按新位置再发范围请求。
  • 大文件上传:方向反过来,前端用 file.slice() 切片分别上传,服务端拼接。这是应用层的方案,HTTP 的 Range 只管下载。

Node 里不写 Content-Length 直接多次 res.write(),HTTP/1.1 下会自动变成 chunked:

require('http').createServer((req, res) => {
  res.write('第一块\n')                     // 立刻发出
  setTimeout(() => res.end('第二块\n'), 1000) // 1 秒后发第二块并结束
}).listen(3000)
// curl -i localhost:3000 能看到 Transfer-Encoding: chunked
@前端进阶之旅: 代码已经复制到剪贴板

面试官追问

追问 1视频页用了 chunked,用户拖到 30 分钟处还是从头加载,为什么?
参考回答

chunked 只是服务器怎么把这次响应分批发出去,客户端没法通过它指定从哪开始。拖进度条要的是范围请求,<video> 会自动发 Range,前提是服务端支持并返回 206。

追问 2要下载一个几 GB 的文件,服务端先全读进内存再返回可以吗?
参考回答

不行,几个人同时下载内存就爆了。用流式读取边读边写,Node 里就是 fs.createReadStream(file).pipe(res)。文件长度已知的话带上 Content-Length 就行,长度未知才用 chunked。

追问 3同一个静态服务既有大日志文本又有视频,统一开 gzip 可以吗?
参考回答

按类型开。文本开,Nginx 用 gzip_types 列出 text/plain、application/json、application/javascript 这些;视频、图片别加进去,压不动还白费 CPU。

追问 4怎么一眼判断一个下载地址支不支持断点续传?
参考回答

curl -I 看响应有没有 Accept-Ranges: bytes,再实际发一个 curl -r 0-99 -I 看是不是 206。只返回 200 就是不支持,下载器只能从头来。

追问 5HTTP/2 下还有 chunked 吗?
参考回答

没有了。HTTP/2 自带二进制分帧,数据天然一帧一帧地发,规范明确不允许用 Transfer-Encoding: chunked。压缩和范围请求在 HTTP/2 里照样用。

# 数据压缩

30 秒速记

  • 浏览器 Accept-Encoding: gzip, deflate, br 报能力 → 服务器挑一个压缩 → Content-Encoding 回告
  • 压缩率 50% ≈ 同带宽下传输时间减半,文本类效果最明显
  • 图片、音视频本身已高度压缩,再 gzip 基本不变小,甚至略大
  • Nginx:gzip on 默认只压 text/html,JS、CSS、JSON 要自己加进 gzip_types
  • 静态资源最好构建时预压缩(gzip_static),小于 1KB 左右的响应没必要压

数据压缩就是服务器用浏览器支持的算法把响应体压小再发,是传大文本最基础、性价比最高的优化。 浏览器在 Accept-Encoding 里列出能解的格式,服务器挑一个压缩,再用 Content-Encoding 告诉浏览器用的哪个。100KB 的 HTML 压到 30KB 很常见,相当于带宽没变网速快了好几倍。但它只对文本有效,图片视频本来就是压缩格式。实际配置时有个坑,Nginx 的 gzip on 默认只压 text/html,JS、CSS 和 JSON 接口要在 gzip_types 里手动加上,不然开了跟没开差不多。

gzip on;
gzip_min_length 1k;            # 太小的响应不压
gzip_types text/css application/javascript application/json image/svg+xml;
gzip_static on;                # 有 app.js.gz 就直接发,不用实时压缩
@前端进阶之旅: 代码已经复制到剪贴板

通常浏览器在发送请求时都会带着“Accept-Encoding”头字段,里面是浏览器支持的压缩格式列表,例如 gzip、deflate、br 等,这样服务器就可以从中选择一种压缩算法,放进“Content-Encoding”响应头里,再把原数据压缩后发给浏览器。

如果压缩率能有 50%,也就是说 100K 的数据能够压缩成 50K 的大小,那么就相当于在带宽不变的情况下网速提升了一倍,加速的效果是非常明显的。

不过这个解决方法也有个缺点,gzip 等压缩算法通常只对文本文件有较好的压缩率,而图片、音频视频等多媒体数据本身就已经是高度压缩的,再用 gzip 处理也不会变小(甚至还有可能会增大一点),所以它就失效了。

不过数据压缩在处理文本的时候效果还是很好的,所以各大网站的服务器都会使用这个手段作为“保底”。例如,在 Nginx 里就会使用“gzip on”指令,启用对“text/html”的压缩

面试官追问

追问 1给 JPEG、视频统一套一层 gzip,负责人说只要压缩就一定更小,对吗?
参考回答

不对。这些格式本身已经压缩过,熵很高,gzip 找不到可压的重复内容,结果基本一样大,加上头部开销还可能略大,CPU 白烧。SVG 例外,它是文本,压缩效果很好。

追问 2开了 gzip on,JS 文件在 Network 面板里还是没有 Content-Encoding,为什么?
参考回答

gzip_types 没包含 application/javascript,默认只压 text/html。另外检查文件是不是小于 gzip_min_length,以及前面是不是有一层代理把压缩去掉了。

追问 3旧浏览器只声明 gzip,网关固定返回 br,有什么问题?
参考回答

客户端解不开,直接白屏或报错。服务端必须在 Accept-Encoding 里出现过的格式中选,br 和 gzip 都准备着,按请求头挑。

追问 4压缩响应体变小了,但缺了 Content-Encoding,会怎样?
参考回答

浏览器把压缩字节当原文解析,页面显示乱码,JSON 直接解析失败。压缩和打标必须在同一层做,常见问题是应用压了没打头,或者网关解压了没删头。

追问 5实时压缩吃 CPU,怎么优化?
参考回答

静态资源构建时就压好,比如用 compression-webpack-plugin 产出 .gz / .br,Nginx 开 gzip_static 直接发。只有接口这类动态内容才实时压,压缩级别用中等,比如 gzip_comp_level 设 5 左右,再高收益很小。

# 分块传输

30 秒速记

  • Transfer-Encoding: chunked:响应体拆成多块依次发,接收方按顺序拼回去
  • 适合长度事先不知道的内容:流式渲染、数据库边查边出的报表、日志流
  • 每块 = 十六进制长度 + \r\n + 数据 + \r\n,长度只算数据本身
  • 以长度 0 的块结束:0\r\n\r\n;没有它客户端会一直等
  • 和 Content-Length 互斥,要么长度已知要么分块;HTTP/2、HTTP/3 不用它,靠自己的分帧

分块传输就是服务器不等内容全部准备好,生成一块发一块,最后发一个长度为 0 的块表示结束。 它解决的是「响应体有多长事先不知道」的问题,比如数据库边查边生成的大页面,没法提前写 Content-Length,就用 Transfer-Encoding: chunked。格式很简单,每块前面一行写这块的字节数(十六进制),后面跟数据。好处是服务端不用把整个响应攒在内存里,浏览器也能早点开始处理,React 18 的流式 SSR 在 HTTP/1.1 下就是靠它。

HTTP/1.1 200 OK
Transfer-Encoding: chunked

5\r\n
Hello\r\n
7\r\n
, world\r\n
0\r\n
\r\n
@前端进阶之旅: 代码已经复制到剪贴板

← HTTP的实体数据HTTP的连接管理 →

fe