动态压缩文件时,是否有标准化方式告知UA未压缩/近似内容长度?
关于通用头部的现状
目前没有标准的HTTP头部专门用于传递未压缩的原始文件大小,你现在使用的X-Uncompressed-Size是业内这类场景中很普遍的自定义做法,很多服务在动态压缩场景下都会采用类似的自定义头来传递原始尺寸信息。
浏览器原生的下载进度条依赖Content-Length和Transfer-Encoding: chunked的配合,但动态压缩时,压缩后的文件大小要在传输过程中才能确定,只能采用分块传输模式,这时候浏览器无法获取准确的最终大小,原生进度条要么显示“无进度”状态,要么只能模糊地展示传输中的动态变化。
实现近似/原始大小进度提示的可行方案
基于历史压缩比估算压缩后大小
日志类文件的压缩比通常比较稳定(一般在3:1到10:1之间),你可以先获取源服务器返回的原始文件大小,然后根据同类型日志的历史平均压缩比,估算出压缩后的近似大小,将这个值设置为响应的Content-Length。这样浏览器就能基于这个估算值展示大致的进度条,虽然最终完成时可能有轻微偏差,但能给用户明确的进度感知。
注意:如果日志内容波动极大(比如突然混入大量不可压缩的二进制数据),这个方法的进度准确性会下降。前端利用自定义头部实现进度展示
既然你已经在响应中携带了X-Uncompressed-Size,可以在前端代码中监听XMLHttpRequest或Fetch的progress事件,用已下载的字节数除以原始未压缩大小来计算近似进度。这种方式下,你可以给用户明确提示“已完成X%的原始文件下载”,比依赖浏览器原生进度条更可控,也更符合用户对“文件大小”的认知(用户关心的是原始日志的大小,而非压缩后的传输大小)。
额外优化思路
如果目标日志文件更新频率不高,可以考虑在代理服务器上提前预压缩并缓存压缩后的文件。这样你就能提前获取到准确的压缩后文件大小,设置精确的Content-Length,浏览器就能显示完全准确的下载进度条了。另外,务必确保响应头中包含Content-Encoding: gzip,这是标准的压缩标识,能保证浏览器正确处理压缩数据。
内容的提问来源于stack exchange,提问作者Tomáš Zato

