latest project uses SpringMvc, and the backend code is as follows:
//Use pic to receive multiple files @RequestMapping("/upload.dhtml") @ResponseBody public String test3(CommonsMultipartFile[] pic) { // do upload return "success"; }
The Android front-end uses AsyncHttpClient, and it is found that the batch upload problem cannot be realized. The problem is as follows.
1. After Android reads the file, it compresses it into InputStream, and finally gets List<InputStream>
List<File> files = ...; List<InputStream> streams = 压缩(files);
2. There are 2 methods for uploading files provided by AsyncHttpClient
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. There is no batch upload method for InputStream. If you use file batch upload, you have to do the following
List<InputStream> streams = ...; File[] files = create temporary files (streams); RequestParams params = getRequestParams(); params.put("pic", files);
Such shortcomings are obvious! ! !
So, how to solve it?
1. Inherit RequestParams and implement a method for adding Streams in batches, as follows:
put(String key, List<InputStream> streams);
2. Modify the back-end code to receive multiple files with different keys, such as:
//Use pic0, pic1, pic2 to receive multiple files @RequestMapping("/upload.dhtml") @ResponseBody public String test3(CommonsMultipartFile pic,CommonsMultipartFile pic1,CommonsMultipartFile pic2) { // do upload return "success"; }
3. The backend abandons Spring's automatic assembly, handles the file upload by itself, and ignores the file name
//Create a generic multipart parser CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext()); / / Determine whether the request has a file upload, that is, a multi-part request if(multipartResolver.isMultipart(request)){ //Convert to multipart request MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest)request; //Get all the file names in the request Iterator<String> iter = multiRequest.getFileNames(); while(iter.hasNext()){ // get the uploaded file MultipartFile file = multiRequest.getFile(iter.next()); if(file != null){ // handle file upload and write to disk } } }
Analysis:
1. Directly pass the pass, and do not modify the third-party library unless it is absolutely necessary. Consider maintenance and stability
. 2. Although the pass is achievable, the implementation method is too discordant, and the number of front-end batch uploads needs to be limited.
3 , Pass off, the performance of this method is much worse than Spring autowiring.
Solution:
use different keys to represent files when uploading from the front end, such as
RequestParams params = getRequestParams(); List<InputStream> streams = ...; for(int i=0;i<strams.size();i++){ params.put("pic["+i+"]",strams.get(i)); }
Backend code:
//Use picObj to receive multiple files @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; } }
Get it done. .