最新项目后端使用SpringMvc,后端代码如下:
//使用 pic,接收多个文件 @RequestMapping("/upload.dhtml") @ResponseBody public String test3(CommonsMultipartFile[] pic) { // do upload return "success"; }
Android 前端使用 AsyncHttpClient,发现无法实现批量上传问题,问题如下。
1、Android 读取到文件后,压缩为 InputStream,最终得到List<InputStream>
List<File> files = ...; List<InputStream> streams = 压缩(files);
2、AsyncHttpClient 提供的上传文件有2个方法
public void put(String key, InputStream stream) { put(key, stream, null); } public void put(String key, File files[]) throws FileNotFoundException { put(key, files, null, null); }
3、对于 InputStream 并没有提供批量上传的方法,如果使用文件批量上传,不得不如下操作
List<InputStream> streams = ...; File[] files = 创建临时文件(streams); RequestParams params = getRequestParams(); params.put("pic", files);
这样的缺点是显而易见的!!!
那么,如何解决呢?
1、继承 RequestParams ,实现一个批量添加Stream的方法,如下:
put(String key, List<InputStream> streams);
2、修改后端代码,使用不同的key接收多个文件,如:
//使用 pic0,pic1,pic2 接收多个文件 @RequestMapping("/upload.dhtml") @ResponseBody public String test3(CommonsMultipartFile pic,CommonsMultipartFile pic1,CommonsMultipartFile pic2) { // do upload return "success"; }
3、后端放弃Spring的自动装配,自己处理文件上传,忽略掉文件名
//创建一个通用的多部分解析器 CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext()); //判断 request 是否有文件上传,即多部分请求 if(multipartResolver.isMultipart(request)){ //转换成多部分request MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest)request; //取得request中的所有文件名 Iterator<String> iter = multiRequest.getFileNames(); while(iter.hasNext()){ //取得上传文件 MultipartFile file = multiRequest.getFile(iter.next()); if(file != null){ // 处理文件上传 写磁盘 } } }
分析:
1、直接Pass掉,不到万不得已不修改第三方库,维护性和稳定性考虑
2、Pass掉,虽然能实现,但是实现方式太不和谐了,而且需要限制前端批量上传的个数
3、Pass掉,这种方式的性能比Spring 自动装配差很多。
解决办法:
前端上传时使用不同的key来表示文件,如
RequestParams params = getRequestParams(); List<InputStream> streams = ...; for(int i=0;i<strams.size();i++){ params.put("pic["+i+"]",strams.get(i)); }
后端代码:
//使用 picObj,接收多个文件 @RequestMapping("/upload.dhtml") @ResponseBody public String test3(Pics picObj) { List<CommonsMultipartFile> pic = picObj.getPic(); for(CommonsMultipartFile file:pic){ // do upload } return "success"; } class Pics{ private List<CommonsMultipartFile> pic; public List<CommonsMultipartFile> getPic() { return pic; } public void setPic(List<CommonsMultipartFile> pic) { this.pic = pic; } }
搞定。。