Spring MVC with ajax file upload and MultipartFile

2020-03-05 09:42发布

问题:

I have an issue using Ajax upload with Spring 3 MVC. I understand that I have to configure multipartResolver bean in spring config, which I've done. Than I can have controller like this

@RequestMapping(value ="/settingsSim")
@ResponseBody
public Map uploadSimSettings(@RequestParam(value="qqfile", required=true) MultipartFile settings) {
 Map<String, Object> ret = new HashMap<String, Object>();
 return ret;
}

The problem is that when I actually send the request to the server (actually valums Ajax file upload does this for me), I get an Internal server error response and nothing is shown in the logs. I am really scratching my head now, as I cannot figure out the problem.

回答1:

When using valums plugin I solved this problem by using @RequestBody Spring annotation. You could rewrite your code as follows:

@RequestMapping(value ="/settingsSim",method=RequestMethod.POST)
@ResponseBody
public Map uploadSimSettings(@RequestBody String body) {
 /*
 some controller logic 
 */
}

Note that the variable body will contain the contents of the uploaded file. Also there is no method declaration in your example which means that your method will be mapped to GET request.

P.S. I also had this "no multipart boundary" problem when parsing request with Apache Commons. HttpServletRequest#getParts() returns just an empty collection.



回答2:

my solution:

@RequestMapping(value = "/create/upload", method = RequestMethod.POST, consumes="multipart/form-data", produces="application/json")
@ResponseBody()
public String handleImageUpload(@RequestParam(value="qqfile", required=true) MultipartFile[] files, 
        @ModelAttribute(value="files") List<MultipartFile> filesSession) throws IOException, FileUploadException {

    if (files.length > 0) {
        filesSession.addAll(Arrays.asList(files));
        // store the bytes somewhere
        return  "{\"success\": true}";
    }
    else {
        return "{\"success\": false}";
    }
}

@RequestMapping(value = "/create/upload", method = RequestMethod.POST, consumes="application/octet-stream", produces="application/json")
@ResponseBody()
public String handleImageUploadApplication(HttpServletRequest request, 
        @ModelAttribute(value="files") List<MultipartFile> filesSession) throws IOException, FileUploadException {

    if (request.getInputStream() != null) {
        // creamos el fichero temporal
        File file = File.createTempFile("file", "valumns",
                RepositoryData.getRepositoryData());
        FileOutputStream fos = new FileOutputStream(file);
        // copiamos contenido
        Streams.copy(request.getInputStream(), fos, true);
        //TODO: 
        //filesSession.addAll(Arrays.asList(files));
        // store the bytes somewhere
        return  "{\"success\": true}";
    }
    else {
        return  "{\"success\": true}";
    }
}

@ExceptionHandler(Exception.class)
@ResponseStatus(value = HttpStatus.SERVICE_UNAVAILABLE)
public void handleException(Exception ex) {
    log.error("Ocurrio un error en el album", ex);
}


回答3:

I had the same problem with the fineuploader (valums), and I tried using request.getInputStream() but did not get it to work.

The @ResponseBody annotation worked but I got the whole body with headers. I thought processing that and stripping off the unwanted chunks was not very elegant. I looked further and found the solution is this post:

problem with spring ajax file upload

Like it is said, I added the bean configuration for the multipart resolver to my spring configuration

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
</bean>

After that, I could easily retrieve my file using

 public @ResponseBody Map ajaxUploadFile(@RequestParam MultipartFile qqfile) { ... }

Don't forget to add the Apache commons-io.jar and commons-fileupload.jar libraries in your project to get it to work



回答4:

@Tomas I encountered same issue while using the same jquery plugin. Please change the Content-Type in the plugin code to xhr.setRequestHeader("Content-Type", "multipart/form-data"); on my plugin its line 1203, after this its now showing a stack trace, however I am encountering another issue where the logs are printing : Sep 8, 2011 9:43:39 AM org.apache.catalina.core.StandardWrapperValve invoke SEVERE: Servlet.service() for servlet dispatcher threw exception org.apache.commons.fileupload.FileUploadException: the request was rejected because no multipart boundary was found



回答5:

As per my observation the file upload plugin does not send a multipart file but sends a stream. I could get it to work by declaring the controller method to accept filename as request param qqfile and the second parameter as httprequest. I then did further processing using request.getinputstream. Hope that helps!

Regards,

Pradyumna