AngularJS Upload Multiple Files with FormData API
How to POST FormData Using the $http Service
When using the FormData API to POST files and data, it is important to set the Content-Type header to undefined
.
var fd = new FormData()
for (var i in $scope.files) {
fd.append("fileToUpload", $scope.files[i]);
}
var config = {headers: {'Content-Type': undefined}};
var httpPromise = $http.post(url, fd, config);
By default the AngularJS framework uses content type application/json
. By setting Content-Type: undefined
, the AngularJS framework omits the content type header allowing the XHR API to set the content type. When sending a FormData object, the XHR API sets the content type to multipart/form-data
with the proper boundaries and base64 encoding.
For more information, see MDN Web API Reference - XHR Send method
How did you get the file information into
$scope.files
?
How to enable <input type="file">
to work with ng-model
This directive also enables <input type="file">
to automatically work with the ng-change
and ng-form
directives.
angular.module("app",[]);
angular.module("app").directive("selectFilesNg", function() {
return {
require: "ngModel",
link: function postLink(scope,elem,attrs,ngModel) {
elem.on("change", function(e) {
var files = elem[0].files;
ngModel.$setViewValue(files);
})
}
}
});
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app">
<h1>AngularJS Input `type=file` Demo</h1>
<input type="file" select-files-ng ng-model="fileArray" multiple>
<code><table ng-show="fileArray.length">
<tr><td>Name</td><td>Date</td><td>Size</td><td>Type</td><tr>
<tr ng-repeat="file in fileArray">
<td>{{file.name}}</td>
<td>{{file.lastModified | date : 'MMMdd,yyyy'}}</td>
<td>{{file.size}}</td>
<td>{{file.type}}</td>
</tr>
</table></code>
</body>
Upload multiple files with FormData using AngularJS and Asp.Net MVC
Change the LoadFileData
function
$scope.LoadFileData = function (files) {
$scope.files.push(files[0]);
};
files
returns a Filelist object and actual file object is at index 0.
Upload data and multiple files with angularjs and Spring mvc
angular part code
var file = $scope.file;
var fd = new FormData();
fd.append('dto', JSON.stringify($scope.ticketdto));
fd.append('file', file);
$http({
method : 'POST',
url : 'url',
headers : {
'Content-Type' : undefined
},
data : fd,
transformRequest : function(data, headersGetterFunction) {
return data;
}
}).then(function(response) {
......
}).catch(function(response) {
......
});
java part
@RequestMapping(value = "/new", method = RequestMethod.POST)
public void createTicket(@RequestParam String dto,
@RequestParam(required = false) MultipartFile file , Authentication authentication) {
....
//convert string ticket to dto using jackson databind
.....
}
filemodel
yourappname.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);
});
});
}
};
}]);
AngularJS Upload and Post Multiple Files
First create a directive as pointed out here
.directive('filesModel', function () {
return {
restrict: 'A',
controller: function ($parse, $element, $attrs, $scope) {
var exp = $parse($attrs.filesModel);
$element.on('change', function () {
exp.assign($scope, this.files);
$scope.$apply();
});
}
};
});
And for the transform function, check this out.
You can use a factory like:
.factory('File', function () {
return {
// Define a function to transform form data
transformRequest: function (data, headersGetter) {
var fd = data ? new FormData() : null;
if (data) {
angular.forEach(data, function (value, key) {
// Is it a file?
if (value instanceof FileList) {
if (value.length == 1) {
fd.append(key, value[0]);
} else {
angular.forEach(value, function (file, index) {
fd.append(key + '_' + index, file);
});
}
}
// Is it an object?
else if (typeof value === 'object') {
fd.append(key, JSON.stringify(value));
} else {
fd.append(key, value);
}
});
}
return fd;
}
};
})
Then for the service:
uploadFiles: function(form){
return $http.post("/api/file-upload/", form, {withCredentials: true, headers: {'Content-Type': undefined }, transformRequest: File.transformRequest})
}
Finally the html:
<input type="file" files-model="<model>"/>
Or this for multiple files
<input type="file" files-model="<model>" multiple/>
How to upload multiple files(each file contains max 1 file) on clicking on submit button?
Here is a working example, hope it helps
var myApp = angular.module('myApp', []);
myApp.directive('fileModel', ['fileUpload', function(fileUpload) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
element.bind("change", function(evt) {
fileUpload.pendingFiles[attrs.fileModel] = evt.target.files[0];
});
}
};
}]);
myApp.factory('fileUpload', ['$http', function($http) {
var service = {
uploadUrl: "https://httpbin.org/post",
pendingFiles: [],
doUpload: doUpload
};
return service;
function doUpload() {
var files = new FormData();
angular.forEach(this.pendingFiles, function(value, key) {
files.append('file', value);
});
return $http.post(this.uploadUrl, files, {
transformRequest: angular.identity,
headers: {
'Content-Type': undefined
}
})
}
}]);
myApp.controller('myCtrl', ['$scope', 'fileUpload', function($scope, fileUpload) {
$scope.fileInputs = [1, 2, 3];
$scope.upload = function(filename) {
fileUpload.doUpload().success(function(success) {
$scope.result = success
});
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp">
<div ng-controller="myCtrl">
<div ng-repeat="fileInput in fileInputs">
<input type="file" file-data="{{fileInput}}" file-model="{{fileInput}}" />
</div>
<br />
<button ng-click="upload()">upload all</button>
<br />
<pre>{{result | json}}</pre>
</div>
</body>
Angular 7 - Upload multiple files along with data and report progress
reportProgress
will only work for the respective HTTP request, so when calling the function http.post
with your formD
form data object, it will only report the progress for that particular request containing all your data.
You will have to split the file upload into multiple requests in order to get progress for each individual upload process. This could be achieved by introducing a FormData
array property, where each array entry contains only one individual file. Then, you could fire a request for each FormData
instance, e.g. via creating your HTTP POST request observables first and then combining them via the RxJS forkJoin
operator.
const httpRequests = this.formDataObjects.map((formData) =>
this.http.post<any>(myUrl, formData,{
reportProgress: true,
observe: 'events',
withCredentials:true
})
);
forkJoin(httpRequests).subscribe(..*your subscription logic here..);
Related Topics
Pkill -F Doesn't Work for Process Killing
How to Get Rid of MySQL Error 'Prepared Statement Needs to Be Re-Prepared'
Jquery Ajax Settimeout After Form Succes Not Redirecting
Upload a File Using File_Get_Contents
How to Limit File Upload Type File Size in PHP
Upload 1Gb Files Using Chunking in PHP
Single Quotes or Double Quotes for Variable Concatenation
Comma Separated Values in MySQL "In" Clause
Sf2 Form:Error Neither the Property ... Nor One of the Methods "Get
How to Render a Datetime Object in a Twig Template
Execute Commands on Remote MAChine via PHP
Uploading in Codeigniter - the Filetype You Are Attempting to Upload Is Not Allowed
PHP Array Behaving Strangely with Key Value 07 & 08
How to Build a JSON Array from MySQL Database
Geo-Search (Distance) in PHP/MySQL (Performance)
.Htaccess Rewriterule to Preserve Get Url Parameters
Soap PHP Fault Parsing Wsdl: Failed to Load External Entity
Form Input Field Names Containing Square Brackets Like Field[Index]