Spring MultipartException: The current request is not a multipart request - angularjs

I'm trying to upload a file with AngularJS and Spring controller.
The Angular controller looks like this:
$scope.uploadFile=function(){
var formData=new FormData();
formData.append("file",file.files[0]);
$http.post('/content-files/upload /', file.files[0], {
transformRequest: function(data, headersGetterFunction) {
return data; // do nothing! FormData is very good!
},
headers: {'Content-Type': undefined }
})
.success(function(){
console.log('Post Succeded !');
})
.error(function(){
console.log('Post Failed .');
});
}
I also try this:
var formData = new FormData();
formData.append('file',file.files[0]);
$http.post('/content-files/upload /', formData, {
headers: { 'Content-Type': undefined },
transformRequest: angular.identity
})
and the Spring controller looks like this:
#RequestMapping(value = "/content-files/upload/", method = RequestMethod.POST )
public #ResponseBody String handleFileUpload( #RequestParam("file") MultipartFile file) {
System.out.println("BrandController.uploadMultipart()");
String name=file.getName();
if (!file.isEmpty()) {
try {
byte[] bytes = file.getBytes();
BufferedOutputStream stream =
new BufferedOutputStream(new FileOutputStream(new File(name)));
stream.write(bytes);
stream.close();
return "You successfully uploaded " + name + "!";
} catch (Exception e) {
return "You failed to upload " + name + " => " + e.getMessage();
}
} else {
return "You failed to upload " + name + " because the file was empty.";
}
}
My html Page is :
<form enctype="multipart/form-data">
<input id="file-0a" class="file" type="file" file-model="myFile" name="myFile" />
<button ng-click="uploadFile()">upload me</button></form>
i have 2 jars in web-inf/lib:commons-upload.jar and commons-io.jar
I add this in my spring configuration file:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="50000000"/>
</bean>
When I'm trying to upload a file, I get the error:
org.springframework.web.multipart.MultipartException: The current request is not a multipart request
When I'm trying to upload a file using MultipartHttpServletRequest in my spring function instead of Multipart i get this error:
java.lang.IllegalStateException: Current request is not of type [org.springframework.web.multipart.MultipartHttpServletRequest]: org.apache.catalina.connector.RequestFacade#196f5636
When i use HttpServletRequest request and i try to cast it i got a ClassCastException.
Nothing change when i cancel enctype="multipart/form-data" from my form Tag

Two things needed:
1. headers: {'Content-Type': 'application/x-www-form-urlencoded'}
2. The data passed should be converted to a URL-encoded string
reference:
enter link description here

I stuck into the same problem. Below is angular code
things you should do:
Remove the Content-Type from headers.
For multi file upload use below code
handleImageUpload = async (event) => {
if (event.target.files && event.target.files) {
const files = event.target.files;
_.map(files, (file) => {
//array for multiple files upload
this.imageData.push(file);
const reader = new FileReader();
//base64 encoded image for preview
reader.onload = async (event: any) => {
this.album.push(event.target.result);
};
reader.readAsDataURL(file);
});
this.uploadedImage = Promise.resolve(this.album);
}
}
In you submit handler use this code
const formData: any = new FormData();
// adding multiple files
this.imageData.map((i) => {
formData.append("files", i);
});
// add objects
_.map(body,(value,key) => {
formData.append(key, value);
});
// delete headers it will be set by browser
headers = headers.delete("Content-Type");
// make a call to api
this.httpClient
.post(url, formData, { headers })
.subscribe((res) => console.log(res));

Related

Uploading an image with multer / react-dropzone

I cannot seem to upload an image to my uploads folder using express,multer and react-dropzone. My code is as follows:
<Dropzone
style={{position: "relative"}}
accept="image/*, video/*"
onDrop={this.onDrop.bind(this)}
onDragEnter={this.onDragEnter.bind(this)}
onDragLeave={this.onDragLeave.bind(this)}
name='avatar'
>
{ dropzoneActive && <div style={overlayStyle}>Drop files...</div> }
<div>
<h2>Dropped files</h2>
{
files.map(f => <div><li>{f.name} - {f.size} bytes</li>
<img style={{height:'100px'}}src={f.preview}/></div>)
}
</div>
</Dropzone>
A basic file upload using the dropzone example. Then my submit function is:
createBlog(){
var file = this.state.files[0];
var file_name = file.name;
//api/blog
fetch('http://localhost:8080/saveBlog', {
method: 'POST',
headers: {
"Accept": 'application/json',
'Content-Type': 'application/json',
//"Content-Type": "application/x-www-form-urlencoded"
},
body: JSON.stringify({
file: file,
file_name: file_name
})
}).then((response) => {
...
}))
}, function(error) {
console.log('error: ',error.message)
})
}
Note that file returns all the properties that image has, E.G. lastModifiedDate, name, preview, size, type, webkitRelativePath.
However, when I pass the data to the server the response I get is :
{ file:
{ preview: 'blob:http://localhost:3000/954e0002-3045-44c4-bcd8-70dc26d0d416'
},
file_name: 'image.jpg' } 'Body'
undefined 'files'
Where my server code involving the image is :
var multer = require('multer');
var upload = multer({ dest: './uploads/' });
...
...
router.post('/saveBlog', upload.single('avatar'), function(req, res, next) {
console.log(req.body, 'Body');
console.log(req.file, 'files');
res.end();
});
I am hoping someone can help tell me why my images are not going to my uploads folder as I have spent a long time trying to figure out this basic example.
Your issue is that you're trying using JSON.stringify() for your request payload and Multer expects and only works with formData. You also need to remove the headers you have or use 'content-type': 'multipart/form-data'
You have:
body: JSON.stringify({
file: file,
file_name: file_name
})
You need to use formData() instead:
createBlog(){
const file = this.state.files[0];
const file_name = file.name;
let data = new FormData();
data.append('file', file);
data.append('file_name', file_name);
fetch('http://localhost:8080/saveBlog', {
method: 'POST',
body: data
}).then((response) => {
...
}))
}, function(error) {
console.log('error: ',error.message)
})
}

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

How to upload files with angularjs and laravel 5.2?

I want to upload an image to the server with angularjs
var fileInputElement = $('input[name=avatar]');
var formData = new FormData();
formData.append("team_name", $('input[name=team_name]').val());
formData.append("associated_users", $('input[name=associated_users]').val()); // number 123456 is immediately converted to a string "123456"
// HTML file input, chosen by user
formData.append("avatar", fileInputElement[0].files);
$http.post('groups', formData)
.then(
function (response) {
console.log(response);
//$scope.teams.push(response.data)
},
function (response) {
console.log(response);
}
);
but in my controller when i return the avatar like this:
return "avatar =>" . Input::file('avatar');
the result is :
data:"avatar =>"
i don't know what's wrong with this code?

Bad Gateway 502 on Openshift NodeJS app when uploading a file

i've got an Application based on NodeJS and AngularJS and pushed it to openshift. But everytime i try to upload something, i get the following error:
POST http://www.domain.de/api/upload/file 502 (Bad Gateway)
Angular sends the data like this:
$scope.newFile = function() {
$scope.id = $scope.group._id;
var fd = new FormData();
var file = $scope.files[0];
fd.append('file', file);
if (file.type!="application/pdf"){
mvNotifier.error("Nur PDF Dateien sind akzeptiert.");
return;
}
$http.post('/api/upload/file', fd, {
transformRequest: angular.identity,
headers:{'Content-Type': undefined}
})
.success(function(d) {
var data = {
name: file.name,
description: $scope.descriptionfile
}
mvNotifier.notify("Bis hier hin klappt alles");
console.log("sucess on uploading ");
mvFactory.POST(data, mvGroup, {_place:"file", _id:$scope.id}).then(function(data) {
$scope.newfile=false;
$scope.group.files.push({name:file.name, description:$scope.descriptionfile});
mvNotifier.notify("Datei hochgeladen");
}, function(reason) {
mvNotifier.error("reason");
})
})
.error(function(data,status,header) {
mvNotifier.error("Upload hat nicht funktioniert.")
console.log("data", data);
console.log("status", status);
console.log("header", header);
})
And the Server routes to a file using busboy to save it:
uploadFile: function(req,res) {
console.log("req",req.files);
if (process.env.OPENSHIFT_DATA_DIR!= undefined) {
var cPath = process.env.OPENSHIFT_DATA_DIR;
} else {
var cPath = path.resolve('..', 'data');
}
var busboy = new Busboy({ headers: req.headers });
req.pipe(busboy);
busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
var wPath = cPath + '/uploads/documents';
file.pipe(fs.createWriteStream(wPath + '/' + filename));
file.on('end', function() {
console.log('File [' + fieldname + '] Finished');
});
});
busboy.on('finish', function() {
console.log('Done parsing form!');
});
res.status(200).end();
}
On Localhost everything is working just fine and the data is saved to the server. but i get the response of bad gateway and this header:
<title>502 Bad Gateway</title>
</head><body>
<h1>Bad Gateway</h1>
<p>The proxy server received an invalid response from an upstream server.<br />
Can someone help me please?
I've resolved the issue. I post it so that someone who has the problem can solve it to.
The Web load balancer at openshift is HAproxy and has issues with the upload because the response of the server wasn't identical with the request because of the content type. I switched from $http from angular to an XHR. That solved the issue and works fine. The content-type i didn't set at all. now it works fine.

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