问题
Form view:
<form enctype="multipart/form-data" ng-submit="upload(file)">
<input type="file" ng-model="modal.file" accept="image/gif" app-filereader /><br />
<br>
<textarea name="description" placeholder="Description" ng-model="description" id="" cols="30" rows="10"></textarea>
<br>
<input type="hidden" name="user" ng-model="user" value="{{ user }}" />
<br>
<input type="submit" value="Submit" class="network-sensitive button button-block button" />
</form>
Directive:
.directive('appFilereader', function(
$q
){
var slice = Array.prototype.slice;
return {
restrict: 'A'
, require: '?ngModel'
, link: function(scope, element, attrs, ngModel){
if(!ngModel) return;
ngModel.$render = function(){}
element.bind('change', function(e){
var element = e.target;
$q.all(slice.call(element.files, 0).map(readFile))
.then(function(values){
if(element.multiple) ngModel.$setViewValue(values);
else ngModel.$setViewValue(values.length ? values[0] : null);
});
function readFile(file) {
var deferred = $q.defer();
var reader = new FileReader()
reader.onload = function(e){
deferred.resolve(e.target.result);
}
reader.onerror = function(e) {
deferred.reject(e);
}
reader.readAsDataURL(file);
return deferred.promise;
}
});
}
};
});
Upload function in my services:
upload: function(file) {
var token = $window.sessionStorage.token;
var url = 'http://url.co/api/posts/creates';
var $cache = $cacheFactory.get('$http');
var deffered = $q.defer();
var data = $cache.get(url);
if(!data) {
$http({
url: url,
method: "POST",
params: { access_token: token },
data: file,
headers: {'Content-Type': undefined },
transformRequest: angular.identity
}).then(function(res) {
deffered.resolve(res);
});
} else {
deffered.resolve(data);
}
return deffered.promise;
}
I've not included the controller code as it's just relaying the form data from the modal to the service and that part's working.
The problem I'm having is that the file is being submitted as encoded data (my knowledge is a bit shaky about binary data and blobs etc). And my API (written in Symfony2) is expecting a normal file submission as opposed to the data string.
So how would I convert that binary blob into an image file I can then submit? Or am I missing something?
回答1:
use this module https://github.com/danialfarid/angular-file-upload is very simple to use.
ex:
var $file;//single file
$scope.sendFiles= function(){
$upload.upload({
url: yourUrl,
method: "POST",
data: { data: $scope.yourOtherObject },
file: $file
}).success(function (data, status, headers, config) {
// file is uploaded successfully
console.log(data);
console.log("File upload SUCCESS");
}).error(function (data, status) {
console.log("File upload FAILED");
});
}
$scope.onFileSelect = function ($files) {
for (var i = 0; i < $files.length; i++) {
$file = $files[i];//set a single file
}
};
HTML CODE
<input type="file" name="myfile" ng-file-select="onFileSelect($files)" />
<button ng-click='sendFiles()'>Send file</button>
回答2:
The problem is the $http service, by default use content-type as application/json and in your case it must be application/x-www-form-urlencoded To solve this you can use the following directive: https://github.com/nervgh/angular-file-upload/wiki/Module-API, it also has support for send data along with the files.
Another aproach is to use the formData object along with XmlHttpRequest in your directive, like this:
var data = new FormData();
var xhr = new XMLHttpRequest();
data.append('file', files[i], files[i].name);
xhr.open('POST', scope.mseUploadFile);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
var result = xhr.responseText;
if (scope.callback) {
scope.$apply(function () {
scope.callback({ $data: result });
});
}
}
else if (xhr.readyState == 4 && xhr.status == 400) {
scope.$apply(function () {
if (scope.onError) {
scope.onError({ $error: xhr.responseText });
}
handleError(xhr.responseText);
});
}
};
xhr.send(data);
来源:https://stackoverflow.com/questions/26162132/how-do-i-upload-a-multipart-form-in-angularjs