You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot+Angular如何实现文件上传下载进度观测

Angular 配合 Spring Boot 实现文件传输进度的方案说明

reportProgress 方案的适用范围

这个配置不是只支持文件上传场景,下载场景同样可以原生支持,不需要额外改造:

  • 上传场景:发起POST/PUT等带请求体的请求传输文件时,设置reportProgress: true + observe: 'events',订阅请求后筛选HttpEventType.UploadProgress类型的事件,就能通过事件携带的loaded(已发送字节数)、total(总字节数)计算上传进度。
  • 下载场景:发起GET请求拉取文件流时,同样开启reportProgress: true,将responseType设为blob避免Angular默认按JSON解析响应,之后筛选HttpEventType.DownloadProgress类型的事件,即可拿到已下载字节数计算进度,和上传的写法几乎一致。

底层实现逻辑

这里先纠正一个常见误解:这个方案完全不需要客户端轮询,也不需要Spring Boot后端做任何进度查询逻辑,和服务端基本无关。
所有进度事件来自浏览器底层的HTTP客户端能力(Angular HttpClient默认基于XMLHttpRequest实现,即便切换到Fetch API也有对应的进度回调标准):

  • 上传进度:浏览器向TCP连接写入请求体数据时,每成功写入一块数据就会触发原生的upload.onprogress回调,已发送字节数是浏览器本地统计的,不需要向服务端询问已接收数据量。
  • 下载进度:浏览器从TCP连接读取服务端返回的响应体数据时,每接收到一块数据就会触发原生的onprogress回调,已接收字节数同样是本地统计的,不需要额外发请求。

注意:事件返回的total值取自HTTP响应头的Content-Length字段,如果Spring Boot接口返回文件时没有手动设置该头,或者开启了分块传输(Transfer-Encoding: chunked),total会返回0,无法计算准确百分比。这种情况只需要在下载接口里给response设置Content-Length为文件实际大小即可,不需要其他改造。

给两个最小实现的代码片段参考:

// Angular 端带进度的文件下载示例
this.http.get('/api/file/download', {
  reportProgress: true,
  observe: 'events',
  responseType: 'blob'
}).subscribe(event => {
  switch (event.type) {
    case HttpEventType.DownloadProgress:
      const progress = Math.round(100 * event.loaded / (event.total || 1));
      console.log(`当前下载进度:${progress}%`);
      break;
    case HttpEventType.Response:
      // 下载完成,处理blob对象,比如触发浏览器保存
      break;
  }
});
// Spring Boot 端文件下载接口核心配置示例
@GetMapping("/api/file/download")
public void downloadFile(HttpServletResponse response) throws IOException {
    File targetFile = new File("/path/to/your/file");
    // 必须设置Content-Length,否则前端拿不到总字节数
    response.setContentLengthLong(targetFile.length());
    response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
    // 后续将文件流写入response即可
}

替代方案对比

不存在绝对最优的方案,根据业务场景选即可:

  • 原生reportProgress方案:
    优点是零额外后端开发量,没有额外的连接/请求开销,实现成本极低,能覆盖90%以上只需要传输层进度的普通文件上传/下载场景,是这类场景的首选。
    缺点是只能感知字节传输的进度,无法感知服务端的业务处理进度——比如上传完大压缩包后,服务端需要解压、校验、入库的阶段,这个方案只会显示进度100%,等待接口最终返回。
  • Websocket/SSE 主动推送方案:
    适合需要感知全链路业务进度的场景,比如大文件分片上传的分片校验、存储进度,或者文件接收完成后的转码、解析、入库等非传输阶段的进度。实现时文件传输本身依然走HTTP接口,服务端在每个处理节点通过长连接主动向前端推送进度即可。
    缺点是需要额外维护长连接的生命周期,后端需要做请求标识和会话的绑定,开发和运维成本更高,大流量场景下长连接的资源开销也远高于普通HTTP请求,只适合复杂业务进度场景,不适合用来做单纯的传输进度统计。
  • 轮询查询方案:
    即客户端定时发请求向服务端查询已处理的数据量,这个方案实时性受轮询间隔影响,还有额外的请求开销,除非是极特殊的兼容性场景,否则现在基本不推荐使用。

内容的提问来源于stack exchange,提问作者Luk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 23:12:33