使用Grails RestResponse获取PNG资源字节数小于预期的问题排查
问题分析与解决方案
我之前在使用Grails Rest客户端获取二进制资源时也碰到过一模一样的问题!字节数总是少一截,后来才发现是默认的消息转换器把二进制数据当成文本处理了,导致数据被错误编码损坏。
问题根源
Grails的RestBuilder默认会注册一系列消息转换器,当你通过restResponse.responseEntity.body获取内容时,如果没有明确指定二进制类型的处理方式,它可能会把PNG这类二进制数据当成字符串来解析(比如用UTF-8编码)。二进制数据里的某些字节序列不符合字符编码规则,会被替换或丢弃,最终导致你拿到的字节数组比实际少。
修复方案
直接从响应的输入流读取原始二进制数据,绕过可能出错的消息转换器处理。修改后的代码如下:
import grails.plugins.rest.client.RestBuilder import grails.plugins.rest.client.RestResponse import org.apache.commons.io.IOUtils // 可以用Apache Commons IO,或者自己实现流读取 String url = "http://localhost:8080/rest-endpoint/image.png" RestBuilder rest = new RestBuilder() RestResponse restResponse = rest.get(url){ auth username, password accept "image/png" contentType "image/png" } // 关键:从输入流读取原始二进制 InputStream imageStream = restResponse.inputStream byte[] png_image = IOUtils.toByteArray(imageStream) imageStream.close() // 记得关闭流 println "length " + png_image.length
如果不想引入Apache Commons IO,也可以用Java原生的方式读取流:
// 原生Java流读取方式 ByteArrayOutputStream baos = new ByteArrayOutputStream() byte[] buffer = new byte[1024] int read while ((read = imageStream.read(buffer)) != -1) { baos.write(buffer, 0, read) } byte[] png_image = baos.toByteArray() baos.close() imageStream.close()
额外验证点
你也可以检查下响应的Content-Length头,对比你读取到的字节数是否一致:
println "Expected length: " + restResponse.headers.getFirst("Content-Length")
这样修改后,应该就能拿到完整的PNG二进制数据了。
内容的提问来源于stack exchange,提问作者user8840545
相关产品推荐
相关产品推荐

