如何从我上传图片的AngularJS $ http POST请求中获取'进度'事件?是否可以在客户端执行此操作,或者我是否需要服务器在接收数据时报告进度?
答案 0 :(得分:17)
您还可以使用简单/轻量级angular-file-upload指令来处理这些内容。 它支持使用FileAPI flash shim对非HTML5浏览器进行拖放,文件进度/中止和文件上传
<div ng-controller="MyCtrl">
<input type="file" ng-file-select="onFileSelect($files)" multiple>
</div>
JS:
//inject angular file upload directive.
angular.module('myApp', ['angularFileUpload']);
var MyCtrl = [ '$scope', '$upload', function($scope, $upload) {
$scope.onFileSelect = function($files) {
//$files: an array of files selected, each file has name, size, and type.
for (var i = 0; i < $files.length; i++) {
var $file = $files[i];
$upload.upload({
url: 'my/upload/url',
file: $file,
progress: function(e){}
}).then(function(data, status, headers, config) {
// file is uploaded successfully
console.log(data);
});
}
}
}];
答案 1 :(得分:16)
使用纯角度:
function upload(data) {
var formData = new FormData();
Object.keys(data).forEach(function(key){formData.append(key, data[key]);});
var defer = $q.defer();
$http({
method: 'POST',
data: formData,
url: <url>,
headers: {'Content-Type': undefined},
uploadEventHandlers: { progress: function(e) {
defer.notify(e.loaded * 100 / e.total);
}}
}).then(defer.resolve.bind(defer), defer.reject.bind(defer));
return defer.promise;
}
和其他地方......
// file is a JS File object
upload({avatar:file}).then(function(responce){
console.log('success :) ', response);
}, function(){
console.log('failed :(');
}, function(progress){
console.log('uploading: ' + Math.floor(progress) + '%');
});
答案 2 :(得分:15)
我认为$ http.post()不能用于此。
至于客户端,它应该与HTML5浏览器一起使用,但您可能必须创建自己的XMLHttpRequest对象和onprogress
侦听器。有关提示,请参阅AngularJS: tracking status of each file being uploaded simultaneously。
答案 3 :(得分:3)
我认为Angular没有内置的东西来处理上传。
我认为最好的办法是使用像jQuery File Upload这样的东西。解决方案的一个想法是创建一个Service,它返回{progress:0}
作为默认值,然后在其自身内部,实现jQuery File Upload的进度更新回调,然后只是不断更新进度。感谢Angular的绑定,上传进度将同步。
angular.module('myApp.services', [])
.factory('Uploader', function() {
var uploaderService = {};
var status = { progress: 0 };
uploaderService.upload = function(inputEl) {
inputEl.fileupload({
/* ... */
progressall: function (e, data) {
status.progress = parseInt(data.loaded / data.total * 100, 10);
}
});
};
return uploaderService;
});
答案 4 :(得分:2)
这是另一种解决方案:
window.XMLHttpRequest = (function (orig) {
if (orig) {
var intercept = [],
result = function () {
var r = new orig();
if (r.upload) {
$(r).on(
'abort error load loadend loadstart progress',
function (e) {
$(document).trigger('upload.XHR', e);
}
);
}
if (intercept.length) {
intercept[0].push({
request:r
});
}
return r;
};
result.grab = function (f) {
intercept.unshift([]);
f();
return intercept.shift();
};
return result;
}
return function () {
try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e1) {}
try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (e2) {}
try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e3) {}
throw new Error("This browser does not support XMLHttpRequest.");
};
}(window.XMLHttpRequest));
注意:
AngularJS目前将对window.XMLHttpRequest
的引用存储为私有XHR
变量,然后使用它:new XHR()
。我怀疑这会改变,所以上面的垫片式代码应该可以正常工作。
Mozilla有一些扩展:XMLHttpRequest
接受可选参数。上面的代码没有处理这个问题,但AngularJS无论如何都不使用这些扩展。
可能的用途之一(如果您想显示所有当前请求,并可能实现一些“取消”按钮):
$(document).on('upload.XHR', function (_e, e) {
switch (e.type) {
// do your thing here
}
});
var list = window.XMLHttpRequest.grab(function () {
// start one or more $http requests here, or put some code
// here that indirectly (but synchronously) starts requests
$http.get(...);
couchDoc.save();
couchDoc.attach(blob, 'filename.ext');
// etc
});
list[0].request.upload.addEventListener(...);
答案 5 :(得分:0)
你可以使用这个我使用简单的角度函数上传文件和$ scope.progressBar变量来检查上传的进度......
$scope.functionName = function(files) {
var file = files[0];
$scope.upload = $upload.upload({
url: 'url',
method: 'POST',
withCredentials: true,
data: {type:'uploadzip'},
file: file, // or list of files ($files) for html5 only
}).progress(function(evt) {
console.log('percent: ' + parseInt(100.0 * evt.loaded / evt.total));
$scope.progressBar = parseInt(100.0 * evt.loaded / evt.total);
}).success(function(data, status, headers, config) {
console.log('upload succesfully...')
}).error(function(err) {
console.log(err.stack);
})
}