We are using AngularJS 1.5.8 , Spring 3.2.17, Jackson 2.6.7;
we need to implement file upload with a JSON DTO object. We are unable to see success with file upload with several configurations and approaches, DTO alone as json request parameter is working fine.
Thanks in advance!
snippets of 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>
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
<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 header:
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
Request Body :
Blank! when DTO being sent alone, it has json string with boundary
Response Header:
Response: HTTP/1.1 400 Bad Request
Response Body :
Required request part 'billPaymentDTO' is not present.
formData.append('billPaymentDTO', angular.toJson(data.billPaymentDTO));doesn't add a request part. Please consult the documentation forFormData.append().