Upload multiple files with Angular to Spring Controller - java

I want to upload to server multiple files. Here is my Angular code:
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);
});
});
}
};
}]);
And part of the controller:
var fd = new FormData();
fd.append('files', $scope.file);
fd.append('ticketDto', JSON.stringify(data));
$http({
method: 'POST',
url: url,
headers: {
'Content-Type': undefined
},
data: fd,
arrayKey: '',
transformRequest: function (data, headersGetterFunction) {
return data;
}
})
The problem is that in controller:
public void createTicket(#RequestParam(value = "files", required = false) List<MultipartFile> files,
Authentication authentication,
#RequestParam(value = "ticketDto", required = false) String name)
'files' list is always empty (I also tried MultipartFile[] instead of list). It works only if in directive return not all files, but one, for example:
scope.$apply(function () {
modelSetter(scope, element[0].files[0]);
});
instead of
scope.$apply(function () {
modelSetter(scope, element[0].files);
});

Finally I got it. The solution is to add all files to the FormData apart, not as list or array:
angular.forEach($scope.file, function (value, key) {
fd.append('files', value);
})
And then in Spring controller:
public void createTicket(#RequestParam(required = false) MultipartFile[] files)
The array contains all appended files.

Related

Multiple files upload using AngularJS and Spring Boot

I am trying to upload multiple files at a time using Spring Boot and AngularJS.
Spring Boot file
#RequestMapping(value = "/fileUpload", method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE )
public #ResponseBody boolean UploadFile(#RequestParam(value = "file", required = true) MultipartFile[] files){
Here I am getting the value of MultipartFile[] files as MultipartFile[0]#17615 instead of an array of MultipartFiles. The length of the array is 0.
HTML File
<input type="file" file-model="myFile" name="filePath" ng-model="filePath" on-click="false" multiple required>
AngularJS file
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);
});
});
}
};
}]);
app.service('fileUpload', ['$http', 'growl', '$state', function ($http, growl, $state) {
this.uploadFileToUrl = function(file, uploadUrl){
var fd = new FormData();
for(let i=0;i<file.length;i++){
fd.append('file', file[i]);
}
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function(data, status, headers) {
.....
})
.error(function(error){
.....
});
}
}]);
app.controller('uploadauditfilectrl', ['$scope', 'fileUpload', '$cookieStore', function($scope, fileUpload, $cookieStore){
$scope.uploadFile = function(){
var file = this.myFile;
var uploadUrl = "/fileUpload/";
fileUpload.uploadFileToUrl(file, uploadUrl);
};
}]);
Can anyone please tell me the mistake I am doing.

File size is zero when passing multiple files to the Spring Controller

I am trying to post a file (single file or multiple files) along with some JSON data using AngularJS and Spring MVC.
I tried as shown below:
JS:
(function () {
'use strict';
var myApp = angular.module('app');
myApp.controller('filesWithJSONController', function ($scope, fileUploadService) {
$scope.uploadFile = function () {
var file = $scope.myFile;
var uploadUrl = myApplnURL + '/showInfo/getInformationTest';", //Url of web service
var fd=new FormData();
angular.forEach($scope.files,function(file){
fd.append('file',file);
});
fd.append('properties', new Blob([JSON.stringify({
"name": "root",
"password": "root"
})], {
type: "application/json"
}));
promise = fileWithJSONService.sendInformation(fd,uploadUrl);
promise.then(function (response) {
$scope.serverResponse = response;
}, function () {
$scope.serverResponse = 'An error has occurred';
})
};
});
})();
(function () {
'use strict';
var myApp = angular.module('app');
myApp.service('fileWithJSONService', function ($http, $q) {
this.sendInformation = function (fd, uploadUrl) {
var deffered = $q.defer();
var config = {
headers : {
'Content-Type': undefined
}
}
$http.post(uploadUrl, fd, config).then(function (response) {
console.log("response " + response);
}, function (errResponse) {
console.error('Error in request' + errResponse);
deferred.reject(errResponse);
});
...
Spring Controller:
#Controller
#RequestMapping("/showInfo")
public class InfoController{
#RequestMapping(value = "/getInformationTest", method = RequestMethod.POST, consumes = {"multipart/form-data"})
#ResponseBody
public String sendInformationTest(#RequestPart("properties") ConnectionProperties properties, #RequestPart("file") List<MultipartFile> multiPartFileList){
System.out.println("In spring controller");
//business logic
}
With the above code, it is showing the multiPartFileList size as zero in Spring Controller.
But if I change the code to take only one file instead of multiple files, it is showing the file information successfully. Any input?
try with:
var fd = new FormData();
fd.append('file', file);//replace with forEach
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,//overrides Angular's default serialization, leaving our data intact.
headers: {'Content-Type': undefined}//lets the browser detect the correct Content-Type as multipart/form-data, and fill in the correct boundary.
})
.success(function(){})
.error(function(){});
Backend - Spring:
#RequestMapping(value ="/upload", method = RequestMethod.POST)
public ResponseEntity handleFileUpload(#RequestParam("file") MultipartFile[] files){
//add the others params & logic
}

Pass model and a string using ajax to Spring MVC

Hi I need to pass the full model and one string from html to Spring controller using AJAX. I use the below code snippet but it doesn't work.
var str = $("#resourceManagement").serialize();
var agreementId = ${agreementId};
var tempCnltName=$modal.find("input[data-type='cnltName']").val();
$.ajax({
type:"POST",
data: {str, tempCnltName},
url: "${AGREEMENT_BASE_URL}/checkDuplicateConsultantOnline",
async: false,
dataType: "json",
success: function (data, status, xhr) {
message = data.errorMsg;
},
error: function () {
}
});
The problem is that if I pass model alone (str) or string alone (tempCnltName) I can get it in controller but I cannot get both together.
My controller is as below:
#RequestMapping(value = "/app/agreement/checkDuplicateConsultantOnline", method = RequestMethod.POST)
public #ResponseBody AjaxResponse checkDuplicateConsultantOnline(
#ModelAttribute("consultantBidModel") ConsultantBidModel model,
#RequestParam(value = "tempCnltName", required = false) String cnltName,
HttpServletRequest request,
HttpSession session) throws Exception {
final Set<String> allCnltNames = new HashSet<>();
String errMessage = "";
if (model.getLeadingCnltName() != null) {
allCnltNames.add(model.getLeadingCnltName().toLowerCase());
}
if (model.getJointVentureConsultants() != null) {
for (ConsultantBidListItem entry : model.getJointVentureConsultants()) {
if (!allCnltNames.add(entry.getCnltName().toLowerCase())) {
errMessage = "Each consultant can only appear once.";
}
}
}
if (model.getSubConsultants() != null) {
for (ConsultantBidListItem entry : model.getSubConsultants()) {
if (!allCnltNames.add(entry.getCnltName().toLowerCase())) {
errMessage = "Each consultant can only appear once.";
}
}
}
AjaxResponse response = new AjaxResponse();
if (errMessage != null) {
response.setSuccess(true);
response.setResponseObject(errMessage);
response.setErrorMsg(errMessage);
}
return response;
}
On the server side, you're already prepared to receive both the model (with #ModelAttribute) and an additional URL parameter (with #RequestParam)
On the client, append the URL parameter to the URL. Assuming that str is your model and tempCnltName is your string to submit to the server:
$.ajax({
type:"POST",
data: str,
url: "${AGREEMENT_BASE_URL}/checkDuplicateConsultantOnline?tempCnltName=" + tempCnltName,
...
try
var strVal = $("#resourceManagement").serialize();
var agreementId = ${agreementId};
var tempCnltNameVal=$modal.find("input[data-type='cnltName']").val();
$.ajax({
type:"POST",
data: {str: strVal, tempCnltName: tempCnltNameVal},
url: "${AGREEMENT_BASE_URL}/checkDuplicateConsultantOnline",
async: false,
dataType: "json",
success: function (data, status, xhr) {
message = data.errorMsg;
},
error: function () {
}
});
Probably the malformed json is causing trouble
Another way of doing the above, add the string to model:
var strVal = "consulName=" + tempCnltName + "&";strVal = strVal + $("#resourceManagement").serialize();
The model can then have a new parameter consulName and we can get the value in Controller.

How to post a json array to java servlet with jquery

I'm currently developing spring mvc application and I need to post JSON array.
When I access request.getParameter("paramValue") to fetch the param attibute, but it returning a null value,
Here is my front-end code:
$.ajax(url, {
async: true,
type: 'post',
contentType: 'application/json',
data: JSON.stringify({
"test":"test value"
})
}).done(function (response) {
console.log(data);
}).fail(function (xhr) {
console.log("request failed");
console.log(xhr);
});
Here is my server-side code:
#RequestMapping(value = "/Products", method = RequestMethod.POST)
public void saveProducts(HttpServletRequest req, HttpServletResponse res) throws Exception {
System.out.println(req.getContentType());
System.out.println(req.getContentLength());
System.out.println(req.getContextPath());
System.out.println(req.getParameterValues("test"));
System.out.println(req.getMethod());
StringBuilder buffer = new StringBuilder();
BufferedReader reader = req.getReader();
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
String data = buffer.toString();
System.out.println(data);
System.out.println(req.getParameter("test"));
}
The output is:
application/json
22
null
POST
{"test" : "Test DAta"}
null
I can't figure out whats going on, please help me.
remove this line in you ajax function
contentType: 'application/json',
and replace this line
data: JSON.stringify({
"test":"test value"
})
with
data: {
"test":"test value"
}
and also you can use
req.getParameter("test")
instead
req.getParameterValues("test")
You can by using this :
var data ={id: 1, name :'test'}
$.ajax(url, {
async: true,
type: 'post',
contentType: 'application/json',
data: data
}).done(function (response) {
console.log(data);
}).fail(function (xhr) {
console.log("request failed");
console.log(xhr);
});
and in server side
create a pojo :
public class Product{
private long id;
private String name;
// getters and setters
add library jackson .
add this method in your controller:
#RequestMapping(value = "/Products", method = RequestMethod.POST)
public RepsoneEntity<? >saveProducts(#requestBody Product pr){
LOG.debug(pr.toString());
return new reRepsoneEntity<Product>(pr,HttpStatus.ACCEPTED);
}
i finally fixed it several annotation and changing the the return type of server side method,
#RequestMapping(value = "/Products", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
public ResponseEntity<?> saveProducts(#RequestParam(value = "data") String brand) {
return ResponseEntity.ok(brand);
}</code>
front end
$.ajax(url, {
async: true,
type: "POST",
data: {"data" : JSON.stringify({"Brand" : "Test Brand"})}
}).done(function (response) {
console.log(response);
}).fail(function (xhr) {
console.log("request failed");
console.log(xhr);
});
and i used org.json to access json objects parsed as text, gson to deal with POJOs
and now it works :)

AngularJS - Spring MVC Rest : Not updating object after POST

I have created a simple app with Spring and AngularJS with CRUD functions.
Now, my scope variable that contains the arraylist that I pass is not updating when I create a new one.
This is my code for my AngularJS controller
$scope.agency = {id: null, name: '', contact: '', employees: []};
$scope.agencies = [];
$scope.getAllAgencies = function() {
AgencyService.getAllAgencies()
.then(
function (response) {
$scope.agencies = response;
}
)
};
$scope.getAllAgencies();
$scope.createAgency = function(agency) {
AgencyService.createAgency(agency)
.then(
$scope.getAllAgencies(),
function(errReponse){
console.error('Error while creating Agency.');
}
);
};
$scope.submit = function () {
console.log("Saving new Agency");
$scope.createAgency($scope.agency);
$scope.reset();
};
$scope.reset = function(){
$scope.agency = {id: null, name: '', contact: '', employees: null};
$scope.myForm.$setPristine(); //reset Form
};
Service
App.factory('AgencyService', ['$http', '$q', function($http, $q) {
return {
getAllAgencies: function() {
return $http.get('/agency')
.then(
function(response) {
return response.data;
},
function(errResponse){
console.error('Error while fetching agencies');
return $q.reject(errResponse);
}
)
},
createAgency: function(agency) {
console.log("Creating Agency");
return $http.post('/agency', agency)
.then(
function (response) {
return response.data;
},
function (errResponse) {
console.error('Error while create agency');
return $q.reject(errResponse);
}
)
}
};
}]);
And these are my methods in Spring
Get Agencies
#RequestMapping(value = "/agency", method = RequestMethod.GET)
public ResponseEntity<List<Agency>> getAllAgencies() {
List<Agency> agencies = agencyService.getAllAgencies();
if (agencies.isEmpty()) {
return new ResponseEntity<List<Agency>>(HttpStatus.NO_CONTENT);
}
return new ResponseEntity<List<Agency>>(agencies, HttpStatus.OK);
}
Creation of Agency
#RequestMapping(value = "/agency", method = RequestMethod.POST)
public ResponseEntity<Void> createAgency(#RequestBody Agency agency, UriComponentsBuilder ucBuilder) {
if(agencyService.isAgencyExists(agency)) {
System.out.println("CONFLICT");
return new ResponseEntity<Void>(HttpStatus.CONFLICT);
}
agencyService.saveAgency(agency);
HttpHeaders headers = new HttpHeaders();
headers.setLocation(ucBuilder.path("/agency/{id}").buildAndExpand(agency.getId()).toUri());
return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
}
Note: that when I debug, after the post method it does not continue to my get method.
There is no error in this, when I reload it gets all including the one I just created.
Thanks!
I think the create agency function call should be like below:
$scope.createAgency = function(agency) {
AgencyService.createAgency(agency)
.then(
$scope.getAllAgencies,
function(errReponse){
console.error('Error while creating Agency.');
}
);
};
first parameter in then should be the function "$scope.getAllAgencies" instead you are passing the value the function returned "$scope.getAllAgencies()".

Categories

Resources