AngularJS: upload multiple images with multipart/form-data [duplicate] - angularjs

This question already has an answer here:
AngularJS Upload Multiple Files with FormData API
(1 answer)
Closed 3 years ago.
Updated:
I'm facing 405 error upon uploading multiple files (images) via multipart/data-form. I'm able to send images in request and seems my payload showing correct boundries. But I'm getting empty response 405 on submit of API and response.status is showing 405 (method not allowed) error. I'm wondering what could be wrong as everything seems fine.
However i do suspect that there might be something to do with boundries in request-payload. I also come to know that browsers change MIME-TYPE when uploading and this conflicts with multipart/formData.
Please advise what could be wrong. Below is my code.
Directive (file-upload)
myApp.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]);
});
});
}
};
}]);
View (html)
<form ng-submit="submit()">
<input type="text" ng-model="for-param">
<input type="text" ng-model="for-param">
<input type="text" ng-model="for-param">
<input type="file" file-model="image01">
<input type="file" file-model="image02">
<button type="submit">Save</button>
</form>
Controller (on-submit)
$scope.submit = function () {
var params = {...};
var data = {
'frond-side-image' : $scope.image01,
'back-side-image': $scope.image02
};
var formData = new $window.FormData();
formData.append("image01", $scope.image01);
formData.append("image02", $scope.image02);
// Service
$http({
method: "POST",
url: "api-url",
headers: { "Content-Type": undefined },
params: params,
data: formData
}).then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
};
Based on above config, following is my request & response
Header Request (after submit)
Content-Type: multipart/form-data; boundary=…--------------147472608521363
Request Payload
-----------------------------1363509831949
Content-Disposition: form-data; name="image01"
stacked_circles.png
-----------------------------1363509831949
Content-Disposition: form-data; name="image01"
stacked_circles.png
-----------------------------1363509831949--
Response
Based on above config I'm getting empty response, but I'm do getting 405 error which is method not allowed.
Please note that later on I'll convert image to base64 to upload on AWS (I'll just post image/base64 to backend than backend will upload it to AWS).
I've created JSFIDDLE for particular query.

Append the two images to the FormData object:
$scope.submit = function () {
var params = {};
var formData = new $window.FormData();
̶f̶o̶r̶m̶D̶a̶t̶a̶.̶a̶p̶p̶e̶n̶d̶(̶"̶f̶i̶l̶e̶"̶,̶ ̶d̶a̶t̶a̶)̶;̶
formData.append("file01", $scope.image01);
formData.append("file02", $scope.image02);
// Service
$http({
method: "POST",
url: "api-url",
headers: { "Content-Type": undefined },
params: params,
data: formData
}).then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
};
When sending files, each file needs its own formData.append call.
Be sure to use the single file version of the file-model directive:
myApp.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(){
̶m̶o̶d̶e̶l̶S̶e̶t̶t̶e̶r̶(̶s̶c̶o̶p̶e̶,̶ ̶e̶l̶e̶m̶e̶n̶t̶[̶0̶]̶.̶f̶i̶l̶e̶s̶)̶;̶
modelSetter(scope, element[0].files[0]);
});
});
}
};
}]);
<form ng-submit="submit()">
<input type="file" file-model="image01">
<input type="file" file-model="image02">
<button type="submit">Save</button>
</form>

Related

AngularJS File Upload, uploaded image is blank?

I'm using angular to upload file to parse.com rest api.
I follow this tutorial AngularJS Upload tutorialspoint and REST upload documentation here REST Upload
Then I modify my code. Here is my code looks like.
//below code inside RegisterController
$scope.upload = function () {
//upload file
var file = $scope.myFile;
console.log('file is ' );
console.dir(file);
console.log(file.name);
var uploadUrl = "http://128.199.249.233:1337/parse/files/"+file.name; //added file.name
fileUpload.uploadFileToUrl(file, uploadUrl);
//end upload file
}
//above code inside RegisterController
//below code outside any controller
rentalkika.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]);
});
});
}
};
}]);
rentalkika.service('fileUpload', ['$http', function ($http) {
this.uploadFileToUrl = function(file, uploadUrl){
var fd = new FormData();
fd.append('file', file);
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {
'X-Parse-Application-Id': 'secret', //added this
'Content-Type': undefined
}
})
.success(function(response){
console.log(response);
})
.error(function(){
});
}
}]);
//above code outside any controller
Here is my HTML
<form ng-controller="RegisterController">
<label>Upload file</label>
<input type="file" name="ktp" file-model="myFile">
<label class="checkbox">
<input type="checkbox">Get hot offers via e-mail
</label>
<input type="submit" value="Sign up" class="btn btn-primary">
<input type="button" value="Upload" ng-click="upload()" class="btn btn-primary">
</form>
It successfully upload file indicated with 201 created status code and I get success response including name and image url.
The image looks like this blank image
Is something missing or wrong with my code?
It's happen because your binary data of image not sent.
Then I use this https://github.com/danialfarid/ng-file-upload and little bit configuration for headers.
And it works.

is it possible to send uploaded file from angularjs to spring controller but by formbean

I have form having text field and file type. I want to send this to controller using form bean. here is my code.following is my js file. from where I'm sending multipart file.
myApp.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]);
});
});
}
};
}]);
myApp.service('fileUpload', ['$http', function ($http) {
this.uploadFileToUrl = function (file, uploadUrl, uploadform) {
var fd = new FormData();
fd.append('file', file);
fd.append("jsondata", JSON.stringify(uploadform));
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function () {
})
.error(function () {
});
}
}]);
myApp.controller('myFileUpload', ['$scope', 'fileUpload', function ($scope, fileUpload) {
$scope.uploadFile = function () {
var file = $scope.myFile;
$scope.uploadform = {};
var uploadUrl = "navigation/uploadexcel";
fileUpload.uploadFileToUrl(file, uploadUrl, $scope.uploadform);
};
}]);
and my controller is..I want to map multipart file and textbox value into firmbean first and from that I want to get my file for further process.
#RequestMapping(value = "/uploadexcel", method = RequestMethod.POST)
public #ResponseBody
String upload(#RequestBody EmployeeFormBean fb) {
String res = null;
try {
MultipartFile f = fb.getFile();
System.out.println("-->"+ f.getOriginalFilename());
} catch (Exception e) {
e.printStackTrace();
}
return res;
}
my jsp code is as following
<div style="background-color: blanchedalmond">
<div ng-controller = "myFileUpload">
<input type="file" file-model="myFile"/>
<input type="text" name="template" ng-model="uploadform.templateName"/>
<button ng-click="uploadFile()">upload me</button>
</div>
</div>
but m getting error as follow...
415 Unsupported Media Type
59ms
angular...DF52B9C (line 103)
HeadersPostResponseHTMLCookies
"NetworkError: 415 Unsupported Media Type - http://localhost:8080/crmdemo1/navigation/uploadexcel"
how to resolve this issue. I dont want to do it by #resuestparam("file")
is it possible to do this using formbean.. and if yes please tell me how can I do it?
You have a problem in the content type of your request, try to add headers = "content-type=multipart/*" , consumes = "application/json" to #RequestMapping. Beside that (in your service fileUpload) change the headers: {'Content-Type': undefined} to headers: {'Content-Type': application/json}. Hope this will help you

Send FormData with other field in AngularJS

I have a form with two input text and one upload. I have to send it to the server but I have some problem concatenating the file with the text. The server expects this answer:
"title=first_input" "text=second_input" "file=my_file.pdf"
This is the html:
<input type="text" ng-model="title">
<input type="text" ng-model="text">
<input type="file" file-model="myFile"/>
<button ng-click="send()">
This is the Controller:
$scope.title = null;
$scope.text = null;
$scope.send = function(){
var file = $scope.myFile;
var uploadUrl = 'my_url';
blockUI.start();
Add.uploadFileToUrl(file, $scope.newPost.title, $scope.newPost.text, uploadUrl);
};
This is the Directive fileModel:
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]);
});
});
}
};
And this is the Service which call the server:
this.uploadFileToUrl = function(file, title, text, uploadUrl){
var fd = new FormData();
fd.append('file', file);
var obj = {
title: title,
text: text,
file: fd
};
var newObj = JSON.stringify(obj);
$http.post(uploadUrl, newObj, {
transformRequest: angular.identity,
headers: {'Content-Type': 'multipart/form-data'}
})
.success(function(){
blockUI.stop();
})
.error(function(error){
toaster.pop('error', 'Errore', error);
});
}
If I try to send, I get Error 400, and the response is: Multipart form parse error - Invalid boundary in multipart: None.
The Payload of Request is: {"title":"sadf","text":"sdfsadf","file":{}}
Don't serialize FormData with POSTing to server. Do this:
this.uploadFileToUrl = function(file, title, text, uploadUrl){
var payload = new FormData();
payload.append("title", title);
payload.append('text', text);
payload.append('file', file);
return $http({
url: uploadUrl,
method: 'POST',
data: payload,
//assign content-type as undefined, the browser
//will assign the correct boundary for us
headers: { 'Content-Type': undefined},
//prevents serializing payload. don't do it.
transformRequest: angular.identity
});
}
Then use it:
MyService.uploadFileToUrl(file, title, text, uploadUrl).then(successCallback).catch(errorCallback);
Here is the complete solution
html code,
create the text anf file upload fields as shown below
<div class="form-group">
<div>
<label for="usr">User Name:</label>
<input type="text" id="usr" ng-model="model.username">
</div>
<div>
<label for="pwd">Password:</label>
<input type="password" id="pwd" ng-model="model.password">
</div><hr>
<div>
<div class="col-lg-6">
<input type="file" file-model="model.somefile"/>
</div>
</div>
<div>
<label for="dob">Dob:</label>
<input type="date" id="dob" ng-model="model.dob">
</div>
<div>
<label for="email">Email:</label>
<input type="email"id="email" ng-model="model.email">
</div>
<button type="submit" ng-click="saveData(model)" >Submit</button>
directive code
create a filemodel directive to parse file
.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]);
});
});
}
};}]);
Service code
append the file and fields to form data and do $http.post as shown below
remember to keep 'Content-Type': undefined
.service('fileUploadService', ['$http', function ($http) {
this.uploadFileToUrl = function(file, username, password, dob, email, uploadUrl){
var myFormData = new FormData();
myFormData.append('file', file);
myFormData.append('username', username);
myFormData.append('password', password);
myFormData.append('dob', dob);
myFormData.append('email', email);
$http.post(uploadUrl, myFormData, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function(){
})
.error(function(){
});
}
}]);
In controller
Now in controller call the service by sending required data to be appended in parameters,
$scope.saveData = function(model){
var file = model.myFile;
var uploadUrl = "/api/createUsers";
fileUpload.uploadFileToUrl(file, model.username, model.password, model.dob, model.email, uploadUrl);
};
You're sending JSON-formatted data to a server which isn't expecting that format. You already provided the format that the server needs, so you'll need to format it yourself which is pretty simple.
var data = '"title='+title+'" "text='+text+'" "file='+file+'"';
$http.post(uploadUrl, data)
This never gonna work, you can't stringify your FormData object.
You should do this:
this.uploadFileToUrl = function(file, title, text, uploadUrl){
var fd = new FormData();
fd.append('title', title);
fd.append('text', text);
fd.append('file', file);
$http.post(uploadUrl, obj, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function(){
blockUI.stop();
})
.error(function(error){
toaster.pop('error', 'Errore', error);
});
}
Using $resource in AngularJS you can do:
task.service.js
$ngTask.factory("$taskService", [
"$resource",
function ($resource) {
var taskModelUrl = 'api/task/';
return {
rest: {
taskUpload: $resource(taskModelUrl, {
id: '#id'
}, {
save: {
method: "POST",
isArray: false,
headers: {"Content-Type": undefined},
transformRequest: angular.identity
}
})
}
};
}
]);
And then use it in a module:
task.module.js
$ngModelTask.controller("taskController", [
"$scope",
"$taskService",
function (
$scope,
$taskService,
) {
$scope.saveTask = function (name, file) {
var newTask,
payload = new FormData();
payload.append("name", name);
payload.append("file", file);
newTask = $taskService.rest.taskUpload.save(payload);
// check if exists
}
}
Assume that we want to get a list of certain images from a PHP server using the POST method.
You have to provide two parameters in the form for the POST method. Here is how you are going to do.
app.controller('gallery-item', function ($scope, $http) {
var url = 'service.php';
var data = new FormData();
data.append("function", 'getImageList');
data.append('dir', 'all');
$http.post(url, data, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
}).then(function (response) {
// This function handles success
console.log('angular:', response);
}, function (response) {
// this function handles error
});
});
I have tested it on my system and it works.

File upload with other data in angularjs with laravel

I want to upload file and other data with angularjs. I am usign FormData but I receive blank array from server side.
This is my form
<form ng-submit="beatSubmit()" name="beatform" enctype="multipart/form-data">
<input type="text" id="beat-name" ng-model="beatData.title" required="required" />
<input type="file" id="image" file-model="image" />
<input type="file" id="tagged_file" file-model="tagged_file" accept="audio/mp3" />
<input type="file" id="untagged-beat" file-model="untagged_file" accept="audio/mp3" />
<input type="text" class="form-control" id="price1" ng-model="beatData.price1">
</form>
Here is my Controller and FileModel directive
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]);
});
});
}
};
}]);
// This is controller part in another file
$scope.beatSubmit = function(){
var image = $scope.image;
var tagged_file = $scope.tagged_file;
var untagged_file = $scope.untagged_file;
var response = BEAT.uploadBeat($scope.beatData,image,tagged_file,untagged_file);
response.success(function(response){
console.log(response);
});
}
And this is my service
uploadBeat:function(data,image,tagged_file,untagged_file){
var fd = new FormData();
fd.append('image', image);
fd.append('tagged_file', tagged_file);
fd.append('untagged_file', untagged_file);
angular.forEach(data, function(value, key) {
fd.append(key,value);
});
console.log(fd); // fd is null , I don't know why?
var req = {
method: 'POST',
transformRequest: angular.identity,
url: 'api/upload_music',
data: fd,
headers:{
'Content-Type': undefined,
}
}
return $http(req);
}
When I tring to get these data from server side It will return null. I spent more time to resolve this But I didn't got any solution. If anyone know Please help me out. Thanks in advance.
Add this header details to the $http
$http({
method: 'POST',
url: '',
headers: {
'X-Requested-With': 'XMLHttpRequest',
'Accept':'*/*',
'Content-type':'application/x-www-form-urlencoded;charset=utf-8'
},
params:data,
timeout:4000
});
Laravel not allowed to submit ajax request without same domain policy
I found an error, I have to remove enctype="multipart/form-data" from form.

Post method angular JS

.controller('LoginConnect', ['$scope', 'connecting',
function(connecting, $scope){
$scope.user = {};
var inputLogin = $scope.user.login;
var inputPassword = $scope.user.password;
$scope.connect = function (){
connecting(ConnectingFactory);
};
}
])
.factory('connecting', ['$http','$q', function ($http,$q,inputLogin, inputPassword, ConnectingFactory){
var ConnectingFactory = {};
console.log(ConnectingFactory);
ConnectingFactory.login = function(){
var deferred = $q.defer();
$http({
method: 'POST',
url: "http://api.tiime-ae.fr/0.1/request/login.php",
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
transformRequest: function(obj) {
var str = [];
for(var p in obj)
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
return str.join("&");
},
data: {login: inputLogin, password: inputPassword}
})
.success(function(result){
deferred.resolve(result);
var promise = deferred.promise;
promise.then(function(result){
console.log(result);
// jsonTab = angular.fromJson(result);
// $scope.result = result["data"];
// $scope.user.token = result["data"];
});
})
};
return ConnectingFactory;
}]);
;
And here the HTML :
<!-- User Connection -->
<form name="userConnect" ng-submit="connect()" novalidate ng-controller="LoginConnect">
<label>
Enter your name:
<input type="text"
name="myEmail"
ng-model="user.login"
/>
</label>
<label>
Enter your Password:
<input type="password"
name="password"
ng-model="user.password"
/>
</label>
<input type="submit" value="Connection">
<p>resultat : {{result}}</p>
<p ng-model="user.token">
token : {{mytoken}}
</p>
<p ng-model="user.datab">
datas : {{datab}}
</p>
<br><br><br>
</form>
Hi, I m new in Angular Js developpement, i have no error but not any data in sent to the API. I think their is no link between my function "connect()" and the factory. Could you help me pls ?
Don't use the success method either way.Both methods have been deprecated.
The $http legacy promise methods success and error have been
deprecated. Use the standard then method instead. If
$httpProvider.useLegacyPromiseExtensions is set to false then these
methods will throw $http/legacy error.
Here is the shortcut method
$http.post('/someUrl', data, config).then(successCallback, errorCallback);
Here is a longer GET method sample
$http({
method: 'GET',
url: '/someUrl'
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
Official Documentation
Regarding the factory , call it correctly as ConnectingFactory.login().
Also, the order here is incorrect, as pointed out by Harry.
['$scope', 'connecting',
function(connecting, $scope){

Resources