RestTemplate上传多文件异常解决

RestTemplate上传文件方法
都知道前端往后端传文件是通过form的形式,后端web程序之间上传,也是通过form表单。使用MultiValueMap类

上传多文件所遇问题

 

这边我需要上传多个文件,在前端传过来时,我的接口是直接用List来接收的。于是我想当然的直接将MultiPartFile列表转化成了ByteArrayResource的list。

通过这种方式上传文件之后,在消息转化器处报错了。错误描述说是不能转换ByteArrayInputStream。

 

问题分析

上面说到消息转换器报错,于是查看我们使用的类,ByteArrayResource。继承自AbstractResource。

 

 

 再看AbstractResource继承自Resource类。

 

 

那么这个Resource的子类,是可以被ResourceHttpMessageConverter解析转换的。开始Debug RestTemplate请求流程。每个HttpMessageConverter都有自己的支持的转换类型。通过查看canRead方法,或者supports方法可以查看支持的转换类型。

 

 

debug RestTemplate处理流程,发现该次请求,使用了AllEncompassingFormHttpMessageConverter,因为我们传输的数据类型是MultiValueMap。这个转换器没有什么方法,大部分直接继承FormHttpMessageConverter,而FormHttpMessageConverter是支持Resource对象转换的,按道理来说应该是可以转换的。

 

 

继续debug,发现在写转换的时候,使用了MappingJackson2HttpMessageConverter,而没有使用ResourceHttpMessageConverter。在writePart方法中,发现转换的对象类型是List,所以调用了支持Object类型转换的Mapping转换器。

 

 

 

 报错原因找到了,尝试改为add文件数组,看了一下form里面的对象类型,是Object,肯定不行,跑完果然还是报错。

 

 

由于通过debug发现,是由于我们传输的对象类型错误,才导致HttpMessageConverter出错,接下来聚焦到对象传输上。查看MultiValueMap的add方法,看到这个add方法,一下就找到了问题所在,它会获取当前Key的LinkedList。然后将对象add到这个list里面。那么我们传递list显然是不科学的。

 

 改为循环add ByteArrayResource,再查看MultiValueMap,已经不是Object了,而是我们的匿名内部类。

 

 再debug到FormHttpMessageConverter中,此时转换这个files所用的转换器,终于是ResourceHttpMessageConverter了,继续运行,果然就可以了,问题解决。

 

 

问题总结

1、RestTemplate上传多文件时,一定要循环add Resource。
2、要重写getFileName方法和contentLength方法。
————————————————
版权声明:本文为CSDN博主「nedjie」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43838174/article/details/109568891

 

posted @ 2021-06-30 16:17  善逸a  阅读(579)  评论(0编辑  收藏  举报