File upload fails with angularjs and spring boot - angularjs

I want to upload file
controller.js
userService.saveProfile($scope.user.profile.companyLogo).then(function(response){
if(response.status==201){
$('#profileModal').hide();
$scope.load();
}
});
service.js
saveProfile:function(logo){
var formData = new FormData();
formData.append("file",logo);
var retVal = $http({
method : 'POST',
url : '/api/user/profile',
transformRequest: angular.identity,
headers: {'Content-Type': undefined},
data: formData
}).then(function(response){
return response;
});
return retVal;
}
Controller.java
#RequestMapping(value="/profile",method = RequestMethod.POST,headers="'Content-Type':'multipart/form-data'")
public ResponseEntity saveProfile(#RequestBody MultipartFile file){
System.out.println(file);
return new ResponseEntity(HttpStatus.CREATED);
}
if I add headers to #RequestMapping I'm getting 404 and if I remove it I'm getting file null
Please suggest me the correct way of doing file upload

It worked!
I removed headers from #RequestMapping and used #RequestPart instead of #RequestBody
#RequestMapping(value="/profile",method = RequestMethod.POST)
public ResponseEntity saveProfile(#RequestPart("file") MultipartFile file){
System.out.println(file);
return new ResponseEntity(HttpStatus.CREATED);
}

Related

Image upload with angularjs and spring boot

I'm trying to upload an image from an angularjs application to a Spring Boot endpoint, but I'm having the problem below:
{"timestamp":1522031262882,"status":400,"error":"Bad Request","exception":"org.springframework.web.multipart.support.MissingServletRequestPartException","message":"Required request part 'image' is not present","path":"/customer/uploadLogo"}
Angularjs code:
function uploadLogo(formdata) {
var formData = new FormData();
formData.append('image', $scope.picture);
return $http.post(defaultConfig.baseUrl + 'customer/uploadLogo', formdata, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined},
});
}
Spring-boot code:
#PostMapping(path = "/uploadLogo")
public void uploadLogo(#RequestParam("image") MultipartFile file) {
System.out.println("");
}
I'm passing "image" on formData, so this exception does not make much sense to me. Has anyone ever had anything like this?

MissingServletRequestPartException: Required request part 'file' is not present

I've been looking at this but it seems my problem is elsewhere. I am trying to upload a file. The input is currently defined as:
<input
type="file"
style="display: none;"
name="file"
multiple
nv-file-select
uploader="uploader">
This is how the upload is performed:
var uploader = $scope.uploader = new FileUploader({
url: 'http://localhost:8080/rest-api/dl4j/we/uploadModel'
});
uploader.onAfterAddingFile = function($modelFile) {
var fd = new FormData();
fd.append('file', $modelFile.file);
$http.post($modelFile.url, fd, {
headers: {
'Content-Type': undefined
},
transformRequest: angular.identity
})
.then(
function (data) {
alert("upload success");
},
function (data, status) {
alert("upload error");
}
);
};
Whereas this is the Spring REST endpoint:
#PostMapping(WordEmbeddingApiPaths.UPLOAD_MODEL)
#RequestMapping(method=RequestMethod.POST, headers={"Content-Type=multipart/form-data"})
public ResponseEntity<WordVectorListDto> uploadModel(
#RequestParam("file") MultipartFile file,
RedirectAttributes redirectAttributes) {
LOGGER.debug("POST uploadModel");
return new ResponseEntity<WordVectorListDto>((WordVectorListDto)null, HttpStatus.OK);
}
The problem is though, that an exception is getting thrown by Spring, telling me that the parameter file is not present:
org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'file' is not present
This is the request information:
How can I make this file upload work?
I guess it can be related to the content type
In your code i see this:
$http.post($modelFile.url, fd, {
headers: {
'Content-Type': undefined
},
transformRequest: angular.identity
})
So you are defining an undefined content-type; You should set multipart/form-data
Try to put this content-type
I hope it's usefull
Angelo

Angular - file upload request, adding #RequestParam

I want to add #RequestParam to my http request so it will match spring MVC #RequestParam.
How can I add this to my file upload request:
/*
#param file - file from input
#param uploadUrl - url
*/
this.uploadFileToUrl = function(file, uploadUrl){
var fd = new FormData();
//add file to FormData
fd.append(file.name, file);
//send request
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function(result){
console.log(result);
})
.error(function(err){
console.log(err);
});
}
In my backend the error is Required String parameter 'filename' is not present
Here is my Spring MVC controller (only the header part):
#Controller
#RequestMapping("/file")
public class FileUploadController {
/**
* Upload single file using Spring Controller
*/
#RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
public #ResponseBody String uploadFileHandler(#RequestParam("filename") String filename, #RequestParam("file") MultipartFile file) {
//rest of the function
}
So I just append another param to my FormData:
fd.append('file', file);
fd.append('filename', file.name);
Match the #RequestParam's.
Thanks.

angular http get, download file from spring mvc server

I'm using apache commons IOUtils copy method to send file from server to angularjs.
This is my controller :
#RequestMapping(value="/download", method = RequestMethod.GET)
public void downloadFile(HttpServletResponse response) {
response.setContentType("image/jpg");
try {
File file = new File(filePath);
InputStream inputStream = new FileInputStream(file);
IOUtils.copy(inputStream, response.getOutputStream());
} catch (...) {
.......
}
In angularJs controller :
$http({
method: 'GET',
url: '.../download',
headers: {'Content-Type': 'image/jpg'}
})
.success(function(data, status){
console.log(data);
var blob = new Blob([data], {type: 'image/jpg'});
saveAs(blob, 'test.jpg');
})
.error(function(data, status){
....
})
When I download the file in the client side, I can't read it. When I open it with notepad++ I find that special characters are modified.
For example, when I open the original file with Notpad++, I get a line like this :
òŽsCJVäl·²HWƒ…;¹(òÈ$ÓÒ«Á‘{S€~9ÎsŠÒogk
The same line, when I open the downloaded file with notepad++ becomes :
��sCJV�l��HW��;�(��$�Ӂҫ��{S�~9�s��ogk
However, when I put the download link (localhost/myApplication/download) directly in a browser, it works correctly. Files are supposed to be encrypted and authorization is needed to download a file, so I have to use angular HTTP get.
Any help would be appreciated.
I had to add responseType to HTTP get request :
$http({
method: 'GET',
url: '.../download',
responseType: 'arraybuffer'
})
.success(function(data, status){
console.log(data);
var blob = new Blob([data], {type: 'image/jpg'});
saveAs(blob, 'test.jpg');
})
.error(function(data, status){
....
})
Now it is working.

Save a file in angular from a http response

I was wondering how I can save a file that is contained in a response from the server in angular ? (So that the file is automatically downloaded when the response arrives)
Edit :
I have a $http post method, and I get pdf data in the response. On success, I want to save the response data as a pdf file.
E. g :
$http({
method: 'POST',
url : 'theUrl',
data: //some array that is received
headers : //content type info
}
.success(function(response) { // I want to save the response as a pdf });
On angular 2... you can do:
import { saveAs } from 'browser-filesaver/FileSaver.js'
downloadFile(data: Response) {
var blob = new Blob([data], {type: 'application/x-tar'});
saveAs(blob, "report.tgz");
}
Using HTML5 FileSaver interface, this can be achieved:
https://github.com/eligrey/FileSaver.js/
Example solution:
//Call API to retrieve file stream using POST request
$http.post("URL", searchData, { responseType: 'arraybuffer' }).then(
response => {
//Download file from response
saveFileAs(response);
},
data => {
//raise error
}
);
function saveFileAs(response) {
var contentDisposition = response.headers("content-disposition");
//Retrieve file name from content-disposition
var fileName = contentDisposition.substr(contentDisposition.indexOf("filename=") + 9);
fileName = fileName.replace(/\"/g, "");
var contentType = response.headers("content-type");
var blob = new Blob([response.data], { type: contentType });
saveAs(blob, fileName);
}
You can't save the document as you don't have access to the users file system in a browser. You could send the URL of the pdf back, then trigger the browsers build in file save / open mechanism by adding a dummy iFrame to the body:
$http({
method: 'POST',
url : 'theUrl',
data: //some array that is received
headers : //content type info
}
.success(function (data) {
if ($('#iframe').length == 0) {
var $iframe = $('<iframe id="iframe" style="display: none"></iframe>');
$('body').append($iframe);
}
$('#iframe').attr('src', {{url to retrieve the file}})
})

Resources