Spring Boot接收Golang发送的PNG字节数异常,如何提取原始PNG?
从Golang服务器向Spring Boot Java应用传输PNG图片时,出现发送与接收字节数不一致的问题,导致无法解析为有效PNG图片。接收端获取到的Content-Type为image/png; charset=utf-8。
请问:
- 针对二进制输出,通常会设置
charset=utf-8吗? - 这是否是字节数差异的原因?
- 如何从响应输入流中提取原始PNG图片?
Go服务器代码片段
w http.ResponseWriter ... w.Header().Set("Content-Disposition", "attachment; filename=\"" + fileNameOfDownload + "\"") w.Header().Set("Content-Length", strconv.Itoa(len(result))) fmt.Println("Length of result: being set:", len(result), strconv.Itoa(len(result)), w.Header().Get("Content-Length")) //Length of result: being set: 60753 60753 60753 w.Header().Set("Allow", "GET,HEAD,POST,OPTIONS,TRACE") w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token , Authorization") w.Header().Set("Access-Control-Allow-Origin", "*") w.Write(result)
Spring Boot客户端代码片段
System.out.println("ResponseDetails:" + httpsCon.getResponseCode() + ":" + httpsCon.getContentType() + ":" + httpsCon.getContentLength() + ":" + httpsCon.getHeaderField("Content-Length")) //ResponseDetails:200:image/png; charset=utf-8:110286:110286
1. 二进制输出是否需要设置charset=utf-8?
不需要。charset参数仅适用于文本类型的Content-Type(比如text/html、application/json),二进制类型(如image/png、application/octet-stream)不存在字符编码的概念,添加charset=utf-8属于错误配置。
2. 这是字节数差异的原因吗?
是的。当Spring Boot看到image/png; charset=utf-8时,会默认以UTF-8编码规则解析响应流,但PNG是二进制数据,这种解析会导致部分字节被错误转换(比如不可编码的字节被替换为UTF-8的替代字符),最终造成接收字节数膨胀、数据损坏,和你遇到的字节数从60753变成110286的情况完全吻合。
3. 如何提取原始PNG图片?
第一步:修复Go服务器的Content-Type配置
在Go代码中明确设置正确的Content-Type,去掉多余的charset参数:
// 添加这行,覆盖默认可能带charset的Content-Type w.Header().Set("Content-Type", "image/png")
这是从根源解决问题的方式,避免客户端触发错误解析逻辑。
第二步:Spring Boot端强制读取原始字节流
如果暂时无法修改Go服务器,在Spring Boot端必须直接操作字节流,禁止使用字符流或带编码的读取方式:
// 获取原始响应输入流 InputStream inputStream = httpsCon.getInputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int readLen; // 按字节读取所有数据 while ((readLen = inputStream.read(buffer)) != -1) { baos.write(buffer, 0, readLen); } // 获取原始PNG字节数组 byte[] rawPngBytes = baos.toByteArray(); // 可直接保存为文件验证 Files.write(Paths.get("output.png"), rawPngBytes);
注意:绝对不要用Reader相关类读取响应,也不要指定任何字符编码,直接以字节为单位处理数据。
额外检查:响应压缩问题
如果Go服务器或中间件(如Nginx)开启了Gzip压缩,而Spring Boot客户端未处理压缩,也会导致字节数异常。可以在Go代码中关闭压缩,或者在Spring Boot请求时添加Accept-Encoding: identity头禁止压缩:
httpsCon.setRequestProperty("Accept-Encoding", "identity");
内容的提问来源于stack exchange,提问作者Krishnan V S

