问题
So ultimately, what I'm doing is trying to upload and post multiple files to a Django backend using AngularJS. I can post a single file, but it seems like when a FileList
object is put in the $http.post
data field, the backend no longer detects any files in the POST request.
Here's what the html looks like:
<form enctype="multipart/form-data" action="upload" method="POST">
<div class="form-group">
<span class="btn btn-info btn-file">
<i class="glyphicon glyphicon-file"></i> Browse
<input class="btn btn-lg btn-info" name="uploadedfile" type="file" accept=".eossa" onchange="angular.element(this).scope().filesUploaded(this.files)" multiple><br/>
</span>
<button type="button" class="btn btn-success" ng-click="uploadFiles()" ng-class="{'disabled':!model.files.length}">
<i class="glyphicon glyphicon-download-alt"></i> Submit
</button>
</div>
<pre ng-repeat="file in model.files" ng-show="file.name">{{file.name}} ({{file.size/1000}} KB) {{file.lastModifiedDate}} </pre>
</form>
And here's the relevant JavaScript:
$scope.filesUploaded = function(files) {
if(files.length < 1) return;
$scope.model.files = files;
$scope.$apply();
};
$scope.uploadFiles = function(){
var fd = new FormData();
fd.append("file", $scope.model.files);
Services.uploadFiles(fd)}
Here's my uploadFiles service:
uploadFiles: function(form){
return $http.post("/api/file-upload/", form, {withCredentials: true, headers: {'Content-Type': undefined }, transformRequest: angular.identity})
},
The backend does not see anything in the request.FILES
in this case; however, if instead of appending $scope.model.files
, I append $scope.model.file[0]
, I do see a file in the request on the backend. In which case, the uploadFiles
function looks like this:
$scope.uploadFiles = function(){
var fd = new FormData();
fd.append("file", $scope.model.files[0]);
Services.uploadFiles(fd)
}
So why can't one append a FileList
to a Form
? How can you POST a FileList?
Thanks
回答1:
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/>
回答2:
I've never tried the method above and this may be a cop out but I thought I would turn you on to some libraries.
I would checkout these two awesome AngularJS file upload Repos. I personally use this one.
Both support easy setup multiple file upload.
ng-file-upload
Here's another.
angular-file-upload
Why put in hours of work when dozens of folks have contributed and done it for you?
来源:https://stackoverflow.com/questions/32996339/angularjs-upload-and-post-multiple-files