Stijn Geukens Stijn Geukens - 1 year ago 69
reST (reStructuredText) Question

Mixed POST submit from AngularJS to Spring RestController

Basically I want to be able to post a form with some fields (JSON) and an attachment (multipart).
Following is actually working code, the problem is that I don't like it so it mainly functions because of workarounds.

Angular controller

$http({
method: 'POST',
url: 'rest/store/logo',
headers: {'Content-Type': undefined },
transformRequest: function (data) {
var formData = new FormData();
//need to convert our json object to a string version of json otherwise the browser will do a 'toString()' on the object which will result in the value '[Object object]' on the server.
formData.append("store", angular.toJson(data.store));
formData.append("file", data.file);
return formData;
},
data: { store: $scope.selectedStore, file: $scope.myFile } //not important but $scope.myFile comes from a directive: http://jsfiddle.net/JeJenny/ZG9re/
});


Spring controller

@RequestMapping(value = "/logo", method = RequestMethod.POST)
public @ResponseBody void updateLogo(HttpServletRequest request, @RequestParam(value = "store", required = false) String store, @RequestPart("file") MultipartFile file) {
System.err.println("store: " + store); //the JSON
StoreEditTO storeEditTO = new Gson().fromJson(store, StoreEditTO.class);
System.err.println("storeEditTO: " + storeEditTO);
}


So, although this works there are 2 things that I'm sure could be simplified:


  1. Angular: not too bad but the code seems to more complicated then it should be

  2. Spring: this is the most disturbing; the file is OK but I need to set the parameter type of
    store
    to
    String
    or Spring will give me a 'no matching editors or conversion strategy found'. Somehow the request parameter is not recognized as being JSON which I guess is because of setting the content-type to undefined but if I don't I get: 'org.springframework.web.multipart.MultipartException: The current request is not a multipart request'?



Posting both separately works just fine by the way. The JSON is converted to the correct type and the file is received. I've already spent hours an getting the mixed mode to work (in a clean way) with no luck so far...

Answer Source

Thanks to above mentioned comment/link I got it working cleanly. I was actually already very close but was missing {type: "application/json"}.

Complete solution:

@RequestMapping(value = "/logo", method = RequestMethod.POST, consumes = {"multipart/form-data"})
public @ResponseBody void updateLogo(@RequestPart(value = "store") StoreEditTO store, @RequestPart("file") MultipartFile file) {
}

$http({
    method: 'POST',
    url: 'rest/store/logo',
    headers: {'Content-Type': undefined },
    transformRequest: function (data) {
        var formData = new FormData();

        formData.append('store', new Blob([angular.toJson(data.store)], {
            type: "application/json"
        }));
        formData.append("file", data.file);
        return formData;
    },
    data: { store: $scope.selectedStore, file: $scope.myFile }

}).
success(function (data, status, headers, config) {
});
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download