按下提交按钮后,一组文件($scope.files
,可以小到一个文件,用户想要多少就多少)通过我FormData
的XMLHttpRequest
角度函数提交$scope.uploadFiles
:
$scope.uploadFiles = function() {
for (var i in $scope.files) {
var form = new FormData();
var xhr = new XMLHttpRequest;
// Additional POST variables required by the API script
form.append('destination', 'workspace://SpacesStore/' + $scope.currentFolderUUID);
form.append('contenttype', 'idocs:document');
form.append('filename', $scope.files[i].name);
form.append('filedata', $scope.files[i]);
form.append('overwrite', false);
xhr.upload.onprogress = function(e) {
// Event listener for when the file is uploading
$scope.$apply(function() {
var percentCompleted;
if (e.lengthComputable) {
percentCompleted = Math.round(e.loaded / e.total * 100);
if (percentCompleted < 1) {
// .uploadStatus will get rendered for the user via the template
$scope.files[i].uploadStatus = 'Uploading...';
} else if (percentCompleted == 100) {
$scope.files[i].uploadStatus = 'Saving...';
} else {
$scope.files[i].uploadStatus = percentCompleted + '%';
}
}
});
};
xhr.upload.onload = function(e) {
// Event listener for when the file completed uploading
$scope.$apply(function() {
$scope.files[i].uploadStatus = 'Uploaded!'
setTimeout(function() {
$scope.$apply(function() {
$scope.files[i].uploadStatus = '';
});
}, 4000);
});
};
xhr.open('POST', '/path/to/upload/script');
xhr.send(form);
}
}
问题是var i
每个文件的初始 for 循环中的增量,并且到事件侦听器触发时,i
已经增量超过files[i]
所需的预期值,仅影响数组中的最后一个。我使用.uploadStatus
这种方式以交互方式向用户显示每个单独文件的进度,因此我需要为$scope.files
. 如何为 Angular 中的单个数组元素分配和跟踪事件?
更新
我重新设计了两个事件监听器,取得了一些成功,但我仍然遇到奇怪的行为:
xhr.upload.onprogress = (function(file) {
// Event listener for while the file is uploading
return function(e) {
$scope.$apply(function() {
var percentCompleted = Math.round(e.loaded / e.total * 100);
if (percentCompleted < 1) {
file.uploadStatus = 'Uploading...';
} else if (percentCompleted == 100) {
file.uploadStatus = 'Saving...';
} else {
file.uploadStatus = percentCompleted + '%';
}
});
}
})($scope.files[i]);
xhr.upload.onload = (function(file, index) {
// Event listener for when the file completed uploading
return function(e) {
$scope.$apply(function() {
file.uploadStatus = 'Uploaded!'
setTimeout(function() {
$scope.$apply(function() {
$scope.files.splice(index,1);
});
}, 2000);
});
}
})($scope.files[i], i);
.onprogress
似乎顺利进行,但是对 进行了一些小的更改.onload
,我现在看到 AngularJS 对其模板的双向绑定有很多奇怪的行为。对于数组中的每个元素$scope.files
,使用上述.uploadStatus
属性给出一个状态。现在我通过传入自执行函数setTimeout
的变量拼接数组中的元素。i
奇怪的是,现在一次上传的上限约为 6 个同时上传,这一定是服务器端的问题,但我注意到随着数组元素的拼接,ng-repeat
模板中的元素,不一定是它应该的元素。我还注意到,在达到 2000 毫秒阈值后,经常有条目没有被拼接。
这让人想起原始问题,即i
在整个事件侦听器的触发过程中引用变量时不可靠?现在我将它传递给匿名自执行.onload
函数,并且拼接使用它来确定它应该删除哪个数组元素,但它不一定会删除正确的元素,并且经常在数组中留下其他元素应该删除它们。