之前公司做文件上传的业务,都是前端调用阿里的OSS,然后返回文件地址到后台。但最近有一个需求,需要后端实现文件上传的功能:前端调用接口传文件流和其他一些请求参数(form-data),后台上传文件,执行业务。用到了apache的文件上传组件,执行到ServletFileUpload.parseRequest(request)时,返回的list为null。先看代码:
简化后的Controller:
简化后的UploadFile方法:
public InputStream UploadFile(HttpServletRequest request) {
try {
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setSizeThreshold(1024 * 1024);
ServletFileUpload upload = new ServletFileUpload(factory);
if (!ServletFileUpload.isMultipartContent(request))
return null;
upload.setFileSizeMax(1024 * 1024 * 100);
upload.setSizeMax(1024 * 1024 * 100);
List<FileItem> list = upload.parseRequest(request);
if (null == list || list.size() == 0) {
return null;
}
String age = list.get(1).getString();
String set = list.get(2).getString();
//do sth
//...
return list.get(0).getInputStream();
} catch (Exception e) {
return null;
}
}
如上,执行到upload.parseRequest(request)时list==null。百度找原因:有些说是已经在Spring配置文件中配置了MultipartResolver,但并没有;有些说是没有在请求头添加enctype="multipart/form-data";或者说jar包没有引用全……这些都不是我遇到的问题。
我心灰意冷心烦气躁百无聊赖心如死灰心灰意懒灰心丧气哀莫大于心死兴味索然万念俱灰意懒心灰意气消沉,公司大佬说:你把Controller里面的@RequestBody String data去掉试试。
神奇!能获取到文件流了。
因为我们公司一般接口都是用json传请求参数,写这个接口的时候也就直接把以前的接口直接粘贴过来改改。至于为什么加了@RequestBody String data就无法获取form/data的内容呢,不知道……
结论:
看下你的接口Controller是否有@RequestBody String data参数,把它去掉试试。
接下的内容可以不看:
根据之前的百度,我在想:SpringMvc已经封装好了文件上传组件,为什么还要用apache的呢?于是继续百度,找到了更加方便上传文件的方法。
先在配置文件中加上文件上传:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8"/>
<property name="maxUploadSize" value="5242880"/>
<property name="maxInMemorySize" value="4096"/>
<property name="resolveLazily" value="true" />
</bean>
接着在Controller中:
@ResponseBody
@RequestMapping(value = "/image/upload", method = RequestMethod.POST)
public String imageUpload(@RequestParam("image") MultipartFile image,
@RequestParam("class_number") long class_number,
@RequestParam("photo_time") long photo_time) {
ImageUploadParams params = ImageUploadParams.toImageUploadParams(class_number, photo_time);
return UploadImage.handler(params, image);
}
在Controller中直接获取文件流@RequestParam("image") MultipartFile image和请求参数,把请求参数转成参数实体,然后就是执行业务啦!
以上!如果哪位大佬知道为什么在Controller参数中加上@RequestBody String data后,获取到的list为null。麻烦留言告诉小弟,小弟先谢过啦!