MultipartFormDataOutput按key排序返回时出现部分响应段缺失问题
问题成因
- 这是Resteasy 4.5.x版本的已知序列化bug:
MultipartFormDataWriter在处理InputStream类型的表单段时,写入完流内容后会直接flush响应输出流,但未正确更新多段响应的状态标记,导致后续添加的表单段被判定为已完成处理,直接跳过序列化,最终响应也不会追加结束分隔边界。 - HashMap的无序性是触发条件:当key的哈希排序后
document.pdf段排在foo.json段前面时,InputStream类型的PDF段先被处理,触发bug导致后面的JSON段丢失;如果顺序反过来,JSON段先被处理就不会触发问题。
解决方案
方案1:修改JSON段的传入类型(最便捷,无需升级框架)
不要给JSON段套ByteArrayInputStream,直接传入字节数组即可,Resteasy对字节数组类型的处理逻辑不会触发流写入的状态bug。
修改后的代码示例:
@POST @Path("test") @Consumes(MediaType.APPLICATION_JSON) @Produces("multipart/form-data") public Response test(MyObject o) { // 处理输入,获取JSON文档和PDF文件对应的字节数组 var output = new MultipartFormDataOutput(); // 直接传入字节数组,不要套ByteArrayInputStream output.addFormData("foo.json", myJsonByteArray, MediaType.APPLICATION_JSON_TYPE.withCharset("UTF-8"), "foo.json"); output.addFormData("document.pdf", new ByteArrayInputStream(myPdfByteArray), MediaType.valueOf("application/pdf"), "document.pdf"); return Response.ok(output).build(); }
方案2:升级框架版本
该bug在Resteasy 4.7.0及以上版本、Quarkus 2.0及以上版本中已被官方修复,升级对应框架版本即可彻底解决问题。
方案3:强制指定表单段顺序(临时适配)
如果暂时无法升级也不想修改参数类型,可以通过反射把MultipartFormDataOutput内置的HashMap替换为LinkedHashMap,手动控制表单段的顺序,保证非InputStream类型的段放在最前面即可。
内容的提问来源于stack exchange,提问作者Flo Ryan
相关产品推荐
相关产品推荐

