被拒绝/中止的多个同步XmlHttpRequests

时间:2016-07-10 23:51:13

标签: javascript ajax file-upload xmlhttprequest

为了获得一些乐趣并了解有关JS和新HTML5规范的更多信息,我决定构建一个文件上传器插件供我个人使用。

在我选择文件后,我将文件发送给我的Web Worker,将其拼接成1mb块并单独上传到我的服务器。我选择单独发送它们以获得个别进度回调和暂停/恢复功能(稍后)。

我遇到的问题是当我选择要上传的大量文件时。如果我只选择8,没问题。如果我选择99,服务器会在关于第20个文件后拒绝/中止,但有时候,它可能会在22,31,18之后停止 - 真正随机。

在中止之前,Firefox可以使用Chrome而不是Chrome。 Chrome称他们失败了#39;和Firefox称他们“流产”#39; Firefox通常会在关于文件40之后中止文件。不仅如此,我的测试服务器也没有响应,并且会重置连接“#39;错误 - 在不到20秒后再次响应。

因为我正在使用Web Worker,所以我将我的XmlHttpRequests设置为同步以允许每个请求在开始新请求之前完成且PHP脚本位于同一个域中,所以我感到很困惑看到请求被拒绝,并希望听到我的代码导致这种情况发生的问题。

这是发送给Worker的插件部分。相当无关,但谁知道:

var worker = new Worker('assets/js/uplift/workers/uplift-worker.js');
worker.onmessage = function(e) {
    console.log(e.data);
};
worker.postMessage({'files':filesArr});

这是uplift-worker.js:

var files = [], p = true;

function upload(chunk) {
    var upliftRequest = new XMLHttpRequest();
    upliftRequest.onreadystatechange = function() {
        if (upliftRequest.readyState == 4 && upliftRequest.status == 200) {
            // do something
        }
    };
    upliftRequest.setRequestHeader("Cache-Control", "no-cache");
    upliftRequest.setRequestHeader("X-Requested-With", "XMLHttpRequest");
    upliftRequest.open('POST', '../php/uplift.php', false);
    upliftRequest.send(chunk);
}

function processFiles() {
    for (var j = 0; j < files.length; j++) {
        var blob = files[j];
        const BYTES_PER_CHUNK = 1024 * 1024; // 1mb chunk sizes.
        const SIZE = blob.size;
        var start = 0,
            end = BYTES_PER_CHUNK;
        while (start < SIZE) {
            var chunk = blob.slice(start, end);
            upload(chunk);
            start = end;
            end = start + BYTES_PER_CHUNK;
        }
        p = j == (files.length -1);
        self.postMessage(blob.name + " uploaded successfully");
    }
}

self.addEventListener('message', function(e) {
    var data__Files = e.data.files;
    for (var j = 0; j < data__Files.length; j++) {
        files.push(data__Files[j]);
    }
    if (p) processFiles();
});

BUGS FOUND:

我设法从Chrome控制台获取此内容:

  

错误:第27行   http://xxxxxxx/demos/uplift/assets/js/uplift/workers/uplift-worker.js   :Uncaught NetworkError:无法执行&#39;发送&#39;上   &#39; XMLHttpRequest&#39;:无法加载   &#39; http://xxxxxxx/demos/uplift/assets/js/uplift/php/uplift.php&#39;

指向工作人员脚本行:upliftRequest.send(chunk);

Firebug根本没有给我很多工作,但这显示了流产的请求:

enter image description here

这显示了随请求发送的标头:

enter image description here

我最初认为这是服务器端的问题,所以我从uplift.php删除了所有PHP,并留下一个空白页面,只是测试上传到浏览器的部分并发布请求,但问题仍在继续。

更新

我开始认为我的托管服务提供商通过使用Apache Mod安全规则来限制请求率 - 可能是为了防止我的IP用暴力攻击服务器。除此之外,我的上传器在我的localhost(MAMP)上工作正常。

我对我的新怀疑做了一些研究。如果我的自制上传插件在向我的主机发送多个文件/请求时遇到了麻烦,那么肯定会有一些其他流行的上传插件可用,使用相同的技术并将文件发布到同一主机,也会在网上发布类似的投诉。这产生了一些好的结果,许多人支持我所拥有的经验。一个人上传了很多图片&#39;使用Uploadify HTML5(也发送个别请求)到同一主机,他的请求也被阻止。我想我最好联系他们,看看他们的限价是什么。

1 个答案:

答案 0 :(得分:0)

可能的问题

我认为这是一个服务器端问题,即使使用普通的php文件..服务器将为每个请求打开一个新线程。在控制台中使用top进行检查。

您正在while循环中上传块,而不必等到上一个块上传完成..

建议

我会创建一个包含所有块的数组并执行upload(chunks)并管理那里的并发,onreadystatechange是一个很好的地方可以使用数组中的下一个块..