AngularJS中的文件上载JSON Spring MVC应用程序400错误请求所需的请求部分不存在

我们使用的是AngularJS 1.5.8,Spring 3.2.17,Jackson 2.6.7;

我们需要使用JSON DTO对象实现文件上传。 我们无法看到使用多种配置和方法的文件上传成功,单独的DTO作为json请求参数工作正常。

提前致谢!

bill_payment.html的片段

app.js

 var app = angular.module('app', [ 'ngRoute', 'ngResource', 'billPaymentAppControllers', 'billPaymentAppServices' ]); ... app.directive('fileModel', ['$parse', function ($parse) { return { restrict: 'A', link: function(scope, element, attrs) { var model = $parse(attrs.fileModel); var modelSetter = model.assign; element.bind('change', function(){ scope.$apply(function(){ modelSetter(scope, element[0].files[0]); }); }); } }; }]); 

billPaymentControllers.js

 var billPaymentAppControllers = angular.module('billPaymentAppControllers', [ 'billPaymentAppServices' ]); billPaymentAppControllers.controller('billPaymentCtrl',['$routeParams', '$route', '$scope', '$location', '$http', '$window', 'BillPaymentService', function($routeParams, $route, $scope, $location, $http, $window, BillPaymentService) { // many other functions $scope.onSaveIRFBillPayment =function(){ BillPaymentService.saveBillPayment.saveBillPaymentDtls( { billPaymentDTO : $scope.billPaymentDTO, depositSlipFile : $scope.attachments.depositSlipFile },function(result) { console.log(result); if(result!=null && result.returnVal!=null && result.returnVal!="" && result.returnVal == "SUCCESS"){ alert("Bill Payment Saved Successfully"); } else { alert("Error while Saving Bill Payment, please contact IT team"); return false; } }); } 

billPaymentServices.js

 billPaymentAppServices.factory('BillPaymentService', function($resource, $http) { return{ saveBillPayment : $resource('agreement/saveIRFBillPayment/', {}, { 'saveBillPaymentDtls' : { method : 'POST', headers: {'Content-Type': undefined}, //transformRequest: angular.identity, transformRequest: function (data) { var formData = new FormData(); console.log("data DTO: "+angular.toJson(data.billPaymentDTO)); formData.append('billPaymentDTO', angular.toJson(data.billPaymentDTO)); //console.log("data file Content: "+data.depositSlipFile); //formData.append('billPaymentDTO', new Blob([angular.toJson(data.billPaymentDTO)], { //type: "application/json" //})); formData.append("file", data.depositSlipFile); return formData; }, transformResponse : function(data) { console.log(data); data = {"returnVal":data}; return data; } } }) } } 

BillPaymentRestController.java

 //@ExceptionHandler(Exception.class) /*** This signature is working for DTO object alone in request ***/ //@RequestMapping(value="/saveIRFBillPayment", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE) //public @ResponseBody String saveIRFBillPayment(@RequestBody String billPaymentDTO,HttpServletRequest request) throws RatingsServiceException, Exception{ /*** tried without consumes attribute, without argument HttpServletRequest request ***/ //@RequestMapping(value="/saveIRFBillPayment", method = RequestMethod.POST) //@ResponseBody String saveIRFBillPayment(@RequestPart("billPaymentDTO") String billPaymentDTO, @RequestPart("file") MultipartFile depositSlipFile) throws RatingsServiceException, Exception{ //public @ResponseBody String saveIRFBillPayment(@RequestParam String billPaymentDTO, @RequestParam("file") MultipartFile depositSlipFile, HttpServletRequest request) throws RatingsServiceException, Exception{ @RequestMapping(value="/saveIRFBillPayment", method = RequestMethod.POST, consumes = {"multipart/form-data"}) @ResponseBody String saveIRFBillPayment(@RequestPart("billPaymentDTO") String billPaymentDTO, HttpServletRequest request, @RequestPart("file") MultipartFile depositSlipFile) throws Exception{ System.out.println("Data inside saveIRFBillPayment:"+billPaymentDTO); System.out.println("\nFile inside saveIRFBillPayment:"+depositSlipFile); ObjectMapper mapper = new ObjectMapper(); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); mapper.setDateFormat(dateFormat); String status="Fail"; try{ BillPaymentDTO billPaymentDTOConverted = mapper.readValue(billPaymentDTO, BillPaymentDTO.class); File ExtractedDepositSlipFile = billPaymentDTOConverted.getDepositSlipFile(); System.out.println("File exists Check: "+ExtractedDepositSlipFile.exists()); //Call to some service status="SUCCESS"; } catch (Exception e) { e.printStackTrace(); } return status; } 

dipatcher-servlet.xml中

                             

请求标题:

 Request: POST /RatingsBD/cc-app/agreement/saveIRFBillPayment HTTP/1.1 X-Requested-With: XMLHttpRequest Accept: application/json, text/plain, */* Content-Type: multipart/form-data; boundary=---------------------------7e01c61b10544 

申请机构:

 Blank! when DTO being sent alone, it has json string with boundary 

响应标题:

 Response: HTTP/1.1 400 Bad Request 

回应机构:

 Required request part 'billPaymentDTO' is not present. 

你尝试过这样的事吗?

 $resource( url, {}, { upload: { method: 'POST', headers: {enctype:'multipart/form-data'} }, } ) 

有一个解决这个问题的方法,尝试通过在表单数据中附加所有billPaymentDTO值以及控制器中的类似文件和类似的请求,以下面的方式更改$http调用。

  var formData= new FormData(); formData.append('id', data.billPaymentDTO.ID); formData.append('contactNumber', data.billPaymentDTO.number); //add all the billPaymentDTO variables as mentioned above formData.append("file", data.depositSlipFile); var uploadUrl = $rootScope.BASE_URL + "agreement/saveIRFBillPayment"; $http.post(uploadUrl, formData, { transformRequest: angular.identity, headers: { 'Content-Type': undefined, 'Accept': 'application/json' } }).success(function(data) { //do something after success }); 

在JAVA方面的控制器中

  @RequestMapping(value="/saveIRFBillPayment", method = RequestMethod.POST) @ResponseBody String saveIRFBillPayment(HttpServletRequest request, HttpServletResponse response, @RequestParam(value="file") MultipartFile document, @RequestParam("id") Long id, @RequestParam("contactNumber") String contactNumber, //similar way add all the attributes of billPaymentDTO here as parameter with required datatypes ) { }