繁体   English   中英

AngularJS JSON Spring MVC 应用程序中的文件上传 400 Bad Request Required 请求部分不存在

[英]File Upload in AngularJS JSON Spring MVC application 400 Bad Request Required request part is not present

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

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

提前致谢!

bill_payment.html 的片段

<form name="billPaymentForm" enctype="multipart/form-data" ng-submit="onSaveIRFBillPayment()">
<!-- some more elements as part of billPaymentDTO -->
<td class="fielddata6">
<input type = "file" file-model = "attachments.depositSlipFile"/>
</td>

应用程序.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

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

    <context:component-scan base-package="com.xxx.xxxxx.restController.addAgreement" />
    <tx:annotation-driven />
    <mvc:annotation-driven />

    <!--        Added by PV - Type conversion -->
    <bean id="jacksonMessageConverter"
        class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>


    <bean
        class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />

    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="messageConverters">
    <list>
          <ref bean="jacksonMessageConverter" />
    </list>
     </property>
    </bean>

    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize" value="268435456" /> <!-- 256 megs -->
    </bean>

    <bean id="methodHandlerExceptionResolver" class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver">
        <property name="messageConverters">
        <list>
            <bean class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter" />
            <bean class="org.springframework.http.converter.FormHttpMessageConverter" />
            <bean class="org.springframework.http.converter.StringHttpMessageConverter" />
        </list>
        </property>
    </bean>
</beans>

请求头:

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
                              ) { }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM