Spring Controller返回GZIP压缩内容遇解码失败及不安全头问题求助
问题排查与修复方案
核心问题分析
- ERR_CONTENT_DECODING_FAILED 200:服务器返回了gzip压缩的二进制数据,但前端未告知浏览器需解压,且服务器手动将二进制压缩流转成String导致数据损坏,浏览器无法解析。
- Refused to set unsafe header:
Accept-Encoding属于浏览器自动管理的请求头,XMLHttpRequest规范禁止手动设置,手动添加会触发该错误。
服务器端修复(推荐用Spring自动压缩)
不要手动实现gzip压缩,Spring自带成熟的压缩配置,更稳定可靠:
在application.properties(或application.yml)中添加以下配置:
# 开启响应压缩 server.compression.enabled=true # 指定需要压缩的MIME类型 server.compression.mime-types=application/json,text/plain # 设置触发压缩的最小响应大小(超过1KB才压缩) server.compression.min-response-size=1024
同时简化Controller代码,直接返回JSON即可,Spring会自动处理压缩:
@GetMapping("/accounts/list/all") public ResponseEntity<List<AccountResponseDTO>> getClients(){ List<AccountResponseDTO> clients = accountService.getAll(); return ResponseEntity.ok(clients); }
若坚持手动压缩(不推荐)
修正手动压缩的代码错误,避免二进制转String导致的数据损坏:
@GetMapping("/accounts/list/all") public ResponseEntity<byte[]> getClients(){ List<AccountResponseDTO> clients = accountService.getAll(); byte[] jsonBytes = null; try { jsonBytes = mapper.writeValueAsBytes(clients); } catch (JsonProcessingException exc) { log.warn(exc.getMessage(), exc); return ResponseEntity.internalServerError().build(); } byte[] compressedBytes = null; try(ByteArrayOutputStream baos = new ByteArrayOutputStream(jsonBytes.length); GZIPOutputStream gzip = new GZIPOutputStream(baos)){ gzip.write(jsonBytes); gzip.finish(); // 确保所有压缩数据写入输出流 compressedBytes = baos.toByteArray(); } catch(IOException exc) { log.warn(exc.getMessage(), exc); return ResponseEntity.internalServerError().build(); } return ResponseEntity.ok() .contentType(MediaType.APPLICATION_JSON) .header(HttpHeaders.CONTENT_ENCODING, "gzip") .header(HttpHeaders.CONTENT_LENGTH, String.valueOf(compressedBytes.length)) .body(compressedBytes); }
前端修复
- 移除手动设置的
Accept-Encoding请求头,浏览器会自动添加该头。 - 将
dataType改为json,让jQuery自动解析JSON响应,无需手动调用JSON.parse()。 - 修正HTML语法错误(class属性加引号,使用Bootstrap标准类
text-center):
$(document).ready(function(){ $('#clients_table tbody').empty(); $.ajax({ type: 'GET', url: '/bankdemo/accounts/list/all', dataType: "json", success: function(response) { $.each(response, function(key, value){ var account = '<tr>' + '<td class="align-middle text-center">'+value.id+'</td>' + '<td class="align-middle text-center">'+value.name+'</td>' + '<td class="align-middle text-center">'+value.surname+'</td>' + '<td class="align-middle text-center">'+value.phone+'</td>' + '<td></td>' + '<td class="align-middle text-center">'+value.birthday+'</td>' + '<td class="align-middle text-center">'+value.active+'</td>' + '</tr>'; $(account).appendTo('#clients_table tbody'); }); }, error: function(xhr, status, error) { console.error('请求异常:', error); } }); });
内容的提问来源于stack exchange,提问作者V-CHO
相关产品推荐
相关产品推荐

