使用Ajax GET请求加载gzip压缩JSON文件失败的问题排查
问题根因
问题出在响应头配置错误,导致浏览器没有自动触发gzip解压逻辑:
- 你在
index.php里写的header('Accept-Encoding: gzip');是完全错误的配置。Accept-Encoding是客户端发往服务端的请求头,用来告诉服务端自己支持的压缩格式,服务端不应该在响应里返回这个头,乱加反而会干扰浏览器对响应内容的正常处理。 - 你全局硬加的
Content-Encoding: gzip头没有作用到.json.gz静态文件的请求上。从你抓包的结果看,这个静态文件请求返回的Content-Type是application/x-gzip,且没有携带Content-Encoding: gzip响应头——这是最核心的问题:浏览器只有在响应头中明确看到Content-Encoding: gzip标识时,才会自动把返回的gzip二进制流解压为明文,否则会直接把原始二进制内容交给前端JS,你拿到的自然是乱码。
之前功能正常大概率是因为原Web服务器配置了预压缩静态文件的自动头规则,后续配置变更把这条规则删掉了,才导致问题出现。
修复方案
方案1(推荐,零前端代码改动)
优先修正服务端配置,这是最符合原有设计逻辑的方案,不需要改任何JS代码,也不需要提前解压文件、引入外部依赖:
- 先把
index.php开头加的两行错误头配置全部删掉,这两行配置没有任何正面作用:
<?php // 删除以下两行错误配置 // header('Accept-Encoding: gzip'); // header('Content-Encoding: gzip'); ?> <html> <head> ... 原有HTML代码
- 修改Web服务器的静态文件响应规则,针对
.json.gz后缀的请求,强制返回两个正确的响应头:Content-Encoding: gzipContent-Type: application/json; charset=utf-8
如果用的是Nginx,直接在对应站点配置中开启gzip_static on;即可,这个内置模块会自动识别目录下预压缩的.gz文件,自动返回正确的响应头,不需要额外手写匹配规则。
如果用的是Apache,在站点配置或.htaccess文件中添加针对.json.gz文件的头匹配规则,给这类请求加上上述两个响应头即可。
配置完成后清浏览器缓存重新请求,在DevTools的Network面板中确认对应json文件请求的响应头带了Content-Encoding: gzip,Content-Type为application/json,原有写的$.ajax请求不用改,设置dataType: "json"就能自动完成解析。
方案2(无法修改服务端配置时使用,无外部依赖)
如果没有权限修改Web服务器配置,可以直接用现代浏览器原生支持的解压API在前端手动处理,不需要引入zlib等任何第三方库:
把原有JS逻辑替换为如下实现即可,核心是用原生DecompressionStream接口手动解压gzip流,再解析JSON:
async function myJsonReader() { const myJsonFileUrl = getUrl(); function doFunStuffWithJsonFile(jsonObject) { // 原有业务逻辑保持不变 } try { const resp = await fetch(myJsonFileUrl); // 初始化gzip解压流 const decompressStream = new DecompressionStream('gzip'); const decompressed = resp.body.pipeThrough(decompressStream); // 读取解压后的文本并解析JSON const jsonText = await new Response(decompressed).text(); const jsonObj = JSON.parse(jsonText); doFunStuffWithJsonFile(jsonObj); } catch (exception) { console.log("Exception " + exception); alert('Failure:' + exception); } }
这个原生API除了已淘汰的IE浏览器外,所有主流现代浏览器(Chrome、Firefox、Edge、Safari 16.4+)都原生支持,不需要引入任何额外依赖。
验证标准
修复完成后符合以下三点即可确认功能正常:
- 对应
.json.gz请求的响应头携带Content-Encoding: gzip - 对应请求的
Content-Type为application/json,不再是application/x-gzip - 页面响应中不会再错误返回
Accept-Encoding头
内容的提问来源于stack exchange,提问作者10GeV
相关产品推荐
相关产品推荐

