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

Brotli压缩文件下载:Chrome与Firefox进度差异及兼容实现问询

关于Brotli压缩文件的XHR下载进度兼容问题

背景信息

用于获取Brotli压缩文件的XHR代码如下:

const xhr = new XMLHttpRequest()
xhr.onprogress = event => {
  console.log(`Progress: ${event.loaded}/${event.total}`)
}    
xhr.open('GET', 'https://example.com/myfile.data.br')
xhr.send()

服务端返回的响应头包含:

  • content-encoding: br
  • content-length: 13934674

实际数据情况:

  • 浏览器网络面板显示实际传输压缩文件大小为13.94 MB(与content-length数值对应)
  • 文件解压后的原始大小为30.30 MB

不同浏览器的onprogress事件表现差异:

  • Firefox:严格遵循content-length头信息,以压缩文件的传输量计算进度,能准确显示真实传输进度与下载速度。
  • Chrome:event.loaded和event.total以解压后的文件大小为基准,但无法获取正确的解压后总大小,导致显示的下载量与实际传输量不符,进度条和速度计算存在误导。

问题解答

1. Chrome的上述行为是否为预期表现?

是预期表现。Chrome在处理带内容编码(如Brotli、Gzip)的XHR请求时,onprogress事件返回的是解压后的数据量,而非网络传输的压缩数据量。这是Chrome对XHR进度事件的实现逻辑,属于浏览器厂商的标准行为,并非Bug。

2. 如何实现兼容Chrome与Firefox的下载进度条?

可以通过以下两种方案实现跨浏览器兼容:

方案一:基于解压后文件大小统一进度计算

让服务端在响应头中添加自定义字段,比如x-uncompressed-length,填入文件解压后的总字节数(示例中为31772160,对应30.30 MB)。前端通过该字段统一以解压后文件大小作为进度基准:

const xhr = new XMLHttpRequest()
xhr.onprogress = event => {
  const uncompressedTotal = parseInt(xhr.getResponseHeader('x-uncompressed-length'))
  if (uncompressedTotal && event.loaded) {
    const progressPercent = (event.loaded / uncompressedTotal) * 100
    console.log(`进度:${progressPercent.toFixed(2)}%`)
  }
}    
xhr.open('GET', 'https://example.com/myfile.data.br')
xhr.send()

这种方案能让两个浏览器的进度显示逻辑一致,用户看到的是最终获取的文件大小对应的进度,体验统一。

方案二:基于实际传输的压缩数据量计算进度

如果需要显示真实的网络传输进度,可以改用Fetch API结合ReadableStream来直接读取原始压缩数据流,统计实际传输的字节数:

fetch('https://example.com/myfile.data.br')
  .then(response => {
    const compressedTotal = parseInt(response.headers.get('content-length'))
    let compressedLoaded = 0
    const reader = response.body.getReader()

    function readChunk() {
      return reader.read().then(({ done, value }) => {
        if (done) {
          console.log('下载完成')
          return
        }
        compressedLoaded += value.length
        const progressPercent = (compressedLoaded / compressedTotal) * 100
        console.log(`传输进度:${progressPercent.toFixed(2)}%`)
        return readChunk()
      })
    }

    return readChunk()
  })

这种方案能在两个浏览器中准确统计网络传输的压缩数据量,显示真实的传输进度与速度。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 08:15:36