MissingServletRequestPartException: Required request part 'file' is not present - angularjs

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

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

Send formdata using angularjs http service

I have to submit user form data. I have done this by using ajaxSubmit but its add one more new JS file into my application. I want to get this done by using angularjs http service. My question is that by using ajaxSubmit I need to send userId id request body and the form data is handle by the ajaxSubmit method itselft. I just want to send the data in a way that ajaxSubmit is doing.
HTML
<form role="form" action="profile_pic">
<div class="cover-50 pull-left pos-relative upload-photo">
<input type="file" onchange="angular.element(this).scope().uploadProfilePic(this)" accept="images/*" capture>
<label>Upload Media</label>
</div>
</form>
Controller
$scope.uploadProfilePic = function(){
$http({
'method': 'POST',
'url': /upload/user/image,
'data': {
'userId' : 457
},
});
// $form.ajaxSubmit({
// type : 'POST',
// url : '/upload/user/image',
// data : {
// 'userId' : 457
// }
// });
}
You could use FormData() to append additional properties to send through $http post.
var data = new FormData();
data.append('userId', 457);
data.append('file', uploadFileUrl);
data.append('abc', "XYZ");
return $http.post('/upload/user/image', data, {
transformRequest: angular.identity,
headers: { 'Content-Type': undefined }
}).then(function (results) {
//results.data
});

Angularjs - downloading a file in a specific location

here is the situation.
I have an angular app that need to be used via a machine on wich you can put an USB key.
Several exports are possible from the corresponding backend and thoses exports (pdf, csv or rtf) need to be downloaded directly on the key, without asking the user.
Furthermore I need to be able to detect if the key is not present and show an error.
I don't think that it is doable using only angular with chromium.
I was thinking of making a local nodejs server on each machine that could access the filesystem for that. It works when using postman with form-data, but I don't know how I can pass a file donwloaded in angular to the nodejs server as a formdata, I keep getting incorrect pdf files.
TLDR :
I need to be able to have a chain like this :
get file from backend in angular
post a request to local (nodejs) server with the downloaded file
receive the file in nodejs to save it on disk
I am open to other ideas if this one doesn't work, as long as I can download this file I am happy.
current nodejs code, that works when i post the file using postman :
router.post('/save', function(req, res, next) {
console.log('savexvbxc');
var fstream;
//test if USB key is available
fs.stat(basePath, function(err, stats) {
if (err) {
console.log('error, key not present');
res.send(412, 'FAILURE');
}
var filename = basePath + 'toti.pdf';
console.log('filename is ' + filename);
if (req.busboy) {
console.log('busboy loaded');
req.busboy.on('file', function(fieldName, fileStream, fileName, encoding, mimeType) {
console.log('Saving: ' + filename + ' ' + fileName);
fstream = fs.createWriteStream(filename);
fileStream.pipe(fstream);
fstream.on('close', function() {
console.log('successfully saved ' + filename);
res.status(200).send('SUCCESS');
});
fstream.on('error', function(error) {
console.log('failed saved ' + filename);
console.log(error);
res.send(500, 'FAILURE');
});
});
req.busboy.on('error', function(error) {
console.log('failed saved ' + filename);
console.log(error);
res.send(500, 'FAILURE');
});
return req.pipe(req.busboy);
} else {
console.log('error, busboy not loaded');
res.send(500, 'FAILURE');
}
});
});
current angular code that do not work:
var dlReq = {
method: 'GET',
url: '/fep/documents/TVFI_FEP_0015_SFS_Specifications_Fonctionnelles_Detaillees_V00.9.pdf',
headers: {
'Content-Type': 'application/pdf',
'Accept': 'http://localhost:4000/fep/documents/TVFI_FEP_0015_SFS_Specifications_Fonctionnelles_Detaillees_V00.9.pdf'
},
responseType: 'arraybuffer'
};
$http(dlReq).then(function(data, status, headers, config) {
console.log(resp);
var file = new Blob([(resp)], {type: 'application/pdf'});
var formdata = new FormData();
formdata.append('file', file);
var request = {
method: 'POST',
url: 'http://localhost:4080/save',
data: formdata,
headers: {
'Content-Type': undefined,
'Accept': '*/*'
}
};
// SEND THE FILES.
$http(request)
.success(function(d) {
console.log('ok', d);
})
.error(function() {
console.log('fail');
});
});
Thank you

Spring MultipartException: The current request is not a multipart request

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));

Custom HTTP headers always get added under "Access-Control-Request-Headers"

I am new to Angular JS. I am writing a simple client to pull data from a HTTP endpoint.
All headers I set are sent over the wire under the header Access-Control-Request-Headers, but not as actual HTTP headers in the request.
delete $http.defaults.headers.common['X-Requested-With'];
var config = {
headers: {
'customHeader1': 'value1'
}
};
$http.defaults.headers.get = {
'customHeader2': 'value2'
};
$http.get("http://localhost:8280/abc",config).success(function(data) {
// alert(data);
$scope.names = data.records;
}).error(function(response, data, status, header) {
alert(status);
});
Could you try that suggestion from the official Angular JS documentation:
To explicitly remove a header automatically added via $httpProvider.defaults.headers on a per request basis, Use the headers property, setting the desired header to undefined. For example:
var req = {
method: 'POST',
url: 'http://example.com',
headers: {
'Content-Type': undefined
},
data: { test: 'test' }
}
$http(req).then(function(){...}, function(){...});

Resources