FileReader > ajax 触发了两次
FileReader > ajax triggered twice
我正在实施文件上传拆分器,使用 FileReader API 将上传的文件拆分成多个部分,然后将其作为单独的 ajax 请求发送到后端。
我的文件部分以某种方式被多次上传,格式如下:
1) 切片 0
2) 切片 0,1
3) 切片 0,1,2
对于较大的文件,当达到一定数量的并行上传时,这通常会导致浏览器崩溃。
我想一次上传一个片段,然后可能会测试并行指定定义数量的片段是否会带来任何性能优势。
代码如下:
function startFileUpload() {
if (jQuery('#upload').length) {
var reader = {};
var file = {};
var slice_size = 4000 * 1024;
var size_done = 0;
var percent_done;
reader = new FileReader();
file = document.querySelector('#upload').files[0];
upload_file(0);
function upload_file(start) {
var next_slice = start + slice_size + 1;
var blob = file.slice(start, next_slice);
reader.readAsDataURL(blob);
reader.addEventListener("loadend", function () {
/*reader.onload = function (event) {*/
if (event.target.readyState !== FileReader.DONE) {
return;
}
// At this point the file data is loaded to event.target.result
jQuery.ajax({
url: 'https://jvdgj5oln9.execute-api.us-east-2.amazonaws.com/Prod/upload',
type: 'POST',
dataType: 'json',
cache: false,
crossDomain: true,
data: {
action: 'upload',
slice_no: (next_slice-1)/slice_size+1,
file_data: event.target.result,
file: file.name,
file_type: file.type
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR, textStatus, errorThrown);
},
success: function (data) {
if (size_done < start + slice_size){
size_done = start + slice_size; //<!--- comment 1
percent_done = Math.floor((size_done / file.size) * 100);
if (next_slice < file.size) {
// Update upload progress
jQuery('#upload_progress').html('Uploading File - ' + percent_done + '%');
// More to upload, call function recursively
upload_file(next_slice);
} else {
// Update upload progress
jQuery('#upload_progress').html('Upload Complete!');
}
}
}
});
});
}
}
}
我已经用 Chrome 调试器检查过 startUpload 只调用了一次。
我还用调试器检查了 "comment 1" 处的代码在每个切片中调用的次数不超过一次,但是我可以看到 ajax 请求是通过 1 触发的,然后是 2,然后在“网络”选项卡中并行 3 个切片。
我也看不到任何自执行的 JavaScript 闭包?所以不清楚是哪个部分触发了多次
每次调用 upload_file()
时,都会将一个新的事件侦听器连接到 reader.loadend
事件。
由于 reader
是在 upload_file()
的范围之外定义的,您最终会在同一个对象上得到一堆事件侦听器。
在 startFileUpload()
中连接事件侦听器,或者将 reader
移动到 upload_file()
范围。
我正在实施文件上传拆分器,使用 FileReader API 将上传的文件拆分成多个部分,然后将其作为单独的 ajax 请求发送到后端。
我的文件部分以某种方式被多次上传,格式如下:
1) 切片 0
2) 切片 0,1
3) 切片 0,1,2
对于较大的文件,当达到一定数量的并行上传时,这通常会导致浏览器崩溃。
我想一次上传一个片段,然后可能会测试并行指定定义数量的片段是否会带来任何性能优势。
代码如下:
function startFileUpload() {
if (jQuery('#upload').length) {
var reader = {};
var file = {};
var slice_size = 4000 * 1024;
var size_done = 0;
var percent_done;
reader = new FileReader();
file = document.querySelector('#upload').files[0];
upload_file(0);
function upload_file(start) {
var next_slice = start + slice_size + 1;
var blob = file.slice(start, next_slice);
reader.readAsDataURL(blob);
reader.addEventListener("loadend", function () {
/*reader.onload = function (event) {*/
if (event.target.readyState !== FileReader.DONE) {
return;
}
// At this point the file data is loaded to event.target.result
jQuery.ajax({
url: 'https://jvdgj5oln9.execute-api.us-east-2.amazonaws.com/Prod/upload',
type: 'POST',
dataType: 'json',
cache: false,
crossDomain: true,
data: {
action: 'upload',
slice_no: (next_slice-1)/slice_size+1,
file_data: event.target.result,
file: file.name,
file_type: file.type
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR, textStatus, errorThrown);
},
success: function (data) {
if (size_done < start + slice_size){
size_done = start + slice_size; //<!--- comment 1
percent_done = Math.floor((size_done / file.size) * 100);
if (next_slice < file.size) {
// Update upload progress
jQuery('#upload_progress').html('Uploading File - ' + percent_done + '%');
// More to upload, call function recursively
upload_file(next_slice);
} else {
// Update upload progress
jQuery('#upload_progress').html('Upload Complete!');
}
}
}
});
});
}
}
}
我已经用 Chrome 调试器检查过 startUpload 只调用了一次。
我还用调试器检查了 "comment 1" 处的代码在每个切片中调用的次数不超过一次,但是我可以看到 ajax 请求是通过 1 触发的,然后是 2,然后在“网络”选项卡中并行 3 个切片。
我也看不到任何自执行的 JavaScript 闭包?所以不清楚是哪个部分触发了多次
每次调用 upload_file()
时,都会将一个新的事件侦听器连接到 reader.loadend
事件。
由于 reader
是在 upload_file()
的范围之外定义的,您最终会在同一个对象上得到一堆事件侦听器。
在 startFileUpload()
中连接事件侦听器,或者将 reader
移动到 upload_file()
范围。