混合 POST 从 AngularJS 提交到 Spring RestController
Mixed POST submit from AngularJS to Spring RestController
基本上,我希望能够 post 包含一些字段 (JSON) 和附件(多部分)的表单。
以下是实际工作的代码,问题是我不喜欢它所以它主要是因为变通方法而起作用。
Angular 控制器
$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 控制器
@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);
}
所以,虽然这可行,但我确信有两件事可以简化:
- Angular:还不错,但代码似乎更复杂,应该是
- Spring:这是最令人不安的;文件没问题,但我需要将
store
的参数类型设置为 String
或 Spring 会给我一个 'no matching editors or conversion strategy found'。不知何故,请求参数未被识别为 JSON,我猜这是因为将内容类型设置为未定义,但如果我不这样做,我会得到:'org.springframework.web.multipart.MultipartException: The current request is not a multipart request'?
顺便说一句,将两者分开发布就可以了。 JSON 被转换为正确的类型并且文件被接收。到目前为止,我已经花了几个小时让混合模式(以一种干净的方式)工作,但运气不佳...
多亏了上面提到的 comment/link 我让它工作得很干净。我其实已经很接近了,但错过了 {type: "application/json"}
.
完整的解决方案:
@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) {
});
基本上,我希望能够 post 包含一些字段 (JSON) 和附件(多部分)的表单。 以下是实际工作的代码,问题是我不喜欢它所以它主要是因为变通方法而起作用。
Angular 控制器
$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 控制器
@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);
}
所以,虽然这可行,但我确信有两件事可以简化:
- Angular:还不错,但代码似乎更复杂,应该是
- Spring:这是最令人不安的;文件没问题,但我需要将
store
的参数类型设置为String
或 Spring 会给我一个 'no matching editors or conversion strategy found'。不知何故,请求参数未被识别为 JSON,我猜这是因为将内容类型设置为未定义,但如果我不这样做,我会得到:'org.springframework.web.multipart.MultipartException: The current request is not a multipart request'?
顺便说一句,将两者分开发布就可以了。 JSON 被转换为正确的类型并且文件被接收。到目前为止,我已经花了几个小时让混合模式(以一种干净的方式)工作,但运气不佳...
多亏了上面提到的 comment/link 我让它工作得很干净。我其实已经很接近了,但错过了 {type: "application/json"}
.
完整的解决方案:
@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) {
});