Angularjs Upload Multiple Files with Formdata API

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



Leave a reply



Submit