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() 范围。