title: jQuery Fileupload (Blueimp) with AngularJS and Spring MVC
body: <p>I'm new to the web development and I'm currently trying to implement a simple file upload for tests purpose.</p>
  
  <p>To sum up, my goal is simply to reproduce this : <a href="http://blueimp.github.io/jQuery-File-Upload/angularjs.html" rel="nofollow">http://blueimp.github.io/jQuery-File-Upload/angularjs.html</a> with Java server side.</p>
  
  <p>Using the jQuery Fileupload plugin and AngularJS I want to make an UI to upload files on a server.
  On the server side I'm using Java and Spring MVC to handle HTTP requests.</p>
  
  <p>However, I'm currently unable to make it works, surely because I don't know what kind of HTTP requests I should handle when using jQuery Fileupload with AngularJS, and the Blueimp documentation did not help me (probably my bad, it's maybe something well-known when you are working with this kind of frameworks).</p>
  
  <p>Here is my current AngularJS controller file (it's basically a copy of the one given with the AngularJS example) :</p>
  
  <pre><code>/* jshint nomen:false */
  /* global window, angular */
  
  (function () {
      'use strict';
  
      var url = '/ExerciseValidator/upload/';
  
      angular.module('file-upload', ['blueimp.fileupload'])
          .config([
              '$httpProvider', 'fileUploadProvider',
              function ($httpProvider, fileUploadProvider) {
                  delete $httpProvider.defaults.headers.common['X-Requested-With'];
                  fileUploadProvider.defaults.redirect = window.location.href.replace(
                      /\/[^\/]*$/,
                      '/cors/result.html?%s'
                  );
  
                  angular.extend(fileUploadProvider.defaults, {
                      // Enable image resizing, except for Android and Opera,
                      // which actually support image resizing, but fail to
                      // send Blob objects via XHR requests:
                      disableImageResize: /Android(?!.*Chrome)|Opera/
                          .test(window.navigator.userAgent),
                      maxFileSize: 999000,
                      acceptFileTypes: /(\.|\/)(c|cpp|h|hpp)$/i
                  });
              }
          ])
  
          .controller('FileUploadController', [
              '$scope', '$http', '$filter', '$window',
              function ($scope, $http) {
                  $scope.options = {
                      url: url
                  };
  
                  $scope.loadingFiles = true;
                  $http.get(url)
                      .then(
                          function (response) {
                              $scope.loadingFiles = false;
                              $scope.queue = response.data.files || [];
                          },
                          function () {
                              $scope.loadingFiles = false;
                          }
                      );
              }
          ])
  
          .controller('FileDestroyController', [
              '$scope', '$http',
              function ($scope, $http) {
                  var file = $scope.file,
                      state;
                  if (file.url) {
                      file.$state = function () {
                          return state;
                      };
                      file.$destroy = function () {
                          state = 'pending';
                          return $http({
                              url: file.deleteUrl,
                              method: file.deleteType
                          }).then(
                              function () {
                                  state = 'resolved';
                                  $scope.clear(file);
                              },
                              function () {
                                  state = 'rejected';
                              }
                          );
                      };
                  } else if (!file.$cancel &amp;&amp; !file._index) {
                      file.$cancel = function () {
                          $scope.clear(file);
                      };
                  }
              }
          ]);
  
  }());
  </code></pre>
  
  <p>In my view I have a form with <code>data-ng-app="file-upload"</code> and <code>data-ng-controller="FileUploadController"</code>.</p>
  
  <p>And here is my current Spring controller :</p>
  
  <pre><code>@Controller
  public class ExerciseValidatorController {
  
  private static final String OUTPUT_FILEPATH = "D:/tmp/";
  
  private final LinkedList&lt;FileMeta&gt; files = new LinkedList&lt;&gt;();
  
  /**
   * Called on index page, returns the file upload page
   * @return the file upload page
   */
  @RequestMapping(value = "/", method = RequestMethod.GET)
  public String showExerciseValidator() {
      return "FileUploadView";
  }
  
  /**
   * Called when files are uploaded, write them to disk and call the validation page
   * @param request the request
   * @param response the response
   * @return TBD
   */
  @RequestMapping(value="/upload/", method = RequestMethod.POST)
  public @ResponseBody
  LinkedList&lt;FileMeta&gt; postUpload(HttpServletRequest request, HttpServletResponse response) {
      if(!(request instanceof MultipartHttpServletRequest)) {
          return null;
      }
  
      Iterator&lt;String&gt; itr = ((MultipartHttpServletRequest)request).getFileNames();
      MultipartFile mpf = null;
  
      while (itr.hasNext()) {
          mpf = ((MultipartHttpServletRequest)request).getFile(itr.next());
  
          final FileMeta fileMeta = new FileMeta();
          fileMeta.setFileName(mpf.getOriginalFilename());
          fileMeta.setFileSize(mpf.getSize() / 1024 + " kB");
          fileMeta.setFileType(mpf.getContentType());
  
          try {
              fileMeta.setBytes(mpf.getBytes());
  
              FileCopyUtils.copy(mpf.getBytes(), new FileOutputStream(OUTPUT_FILEPATH + mpf.getOriginalFilename()));
          } catch (IOException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          }
  
          files.add(fileMeta);
      }
  
      return files;
  }
  }
  </code></pre>
  
  <p>When I use Firebug to test my view, I get the following error : "NetworkError: 405 Method Not Allowed - <a href="http://localhost:8080/ExerciseValidator/upload/" rel="nofollow">http://localhost:8080/ExerciseValidator/upload/</a>"</p>
  
  <p>And nothing happens when I try to upload a file: I can select a file in my hard drive, but it is not shown in the list of files that can be uploaded.</p>
  
  <p>I also tried to add a handler for the GET method on /upload/ in my Spring controller. But even though it get rid of the 405 error, I don't know what should I do with this request. Moreover, I did not notice any improvement in the UI: the list of uploadable files did not show up.</p>
  
  <p>Does anyone have an idea of what should I do ?</p>