Spring MVC 4 AJAX upload MultipartFile with extra parameters
<p>I'm currently developing a <strong>file upload with AJAX</strong> (jQuery) and <strong>Spring MVC 4</strong>. Besides the file itself I have to send some extra parameters, such as a description of the file being uploaded. I'm using an <code>$.ajax()</code> call that sends a <code>FormData</code> object along with my CSRF token, like described below:</p>

<pre><code>var formdata = new FormData();
    formdata.append("description", $('#description').val());
    formdata.append("file", $("#file")[0].files[0]);

$.ajax({
    url: '/upload',
    type: 'POST',
    headers : {"X-CSRF-TOKEN" : $('#myToken').val()}
    data: formdata,
    enctype: 'multipart/form-data',
    processData: false,
    contentType: false,
    success: function (data) {
        alert("Data Uploaded: "+data);
    }
});
</code></pre>

<p>I've found multiple examples of how to upload files using javascript's FormData object along with a Spring controller that receives a <code>MultipartFile</code> object, but when I try to retrieve the other parameters using <code>@RequestParam</code> I end up getting errors. Below is an example of what I was trying (<strong>which didn't work</strong>):</p>

<pre><code>@RequestMapping(value = "/upload", method = RequestMethod.POST)
@ResponseBody
public boolean uploadFile(
        @RequestParam(value = "file") MultipartFile file, 
        @RequestParam(value = "description") String description) {

    //Do stuff...

}
</code></pre>

<p>After a lot of research and attempting different approaches, I found out that I could declare <code>HttpServletRequest</code> as a parameter and it would allow me to retrieve each parameter (but not the file itself). <strong>Below is an working example</strong>:</p>

<pre><code>@RequestMapping(value = "/upload", method = RequestMethod.POST)
@ResponseBody
public boolean uploadFile(
        @RequestParam(value = "file") MultipartFile file, 
        final HttpServletRequest request) {

    String description = request.getParameter("description");

    //Do some other stuff...

}
</code></pre>

<p>Even though the example above worked, the fact that I couldn't use annotations and have my parameters explicit in the method's signature was bugging me. So I tried a different approach changing the <code>@PRequestParam</code> annotation for a <code>@ModelAttribute</code> annotation, which surprisingly worked.</p>

<h2>My questions are:</h2>

<ol>
<li><p><strong>Why didn't <code>@RequestParam</code> worked, if the parameter was retrievable in the <code>HttpServletRequest</code> object?</strong></p></li>
<li><p><strong>Why did <code>@ModelAttribute</code> worked? Should I use it instead of retrieving things explicitly from <code>HttpServletRequest</code>?</strong></p></li>
</ol>