在循环中使用 xhr 对象进行 html5 分块上传

Posted

技术标签:

【中文标题】在循环中使用 xhr 对象进行 html5 分块上传【英文标题】:Using xhr object for html5 chunked upload in a loop 【发布时间】:2012-08-27 11:22:04 【问题描述】:

专家,我在循环通过我为可恢复分块上传创建的 BLOB 块时遇到问题。我遵循的方法如下: 我使用 Blob.slice() 将要上传的文件分块,将所有块推送到队列中并尝试将它们发送到我的服务器。

我面临的问题是关于循环块。第一个块发送成功,我最终在下面提到的上传下一个方法中,从委托给 xhr.onreadystatechange 的函数中。到目前为止一切顺利,但是这段代码在发送前两个块后停止并且没有循环。

以下代码是我目前所取得的成果:

uploadFile: function(item, location, start, isresume) 
        var blob = item.file;

        const BYTES_PER_CHUNK = 1024 * 200 * 10; 
        const SIZE = blob.size;

        var chunkId = 0;
        var end = BYTES_PER_CHUNK;

        while(start < SIZE) 
            var chunkObj = ;
            // Note: blob.slice has changed semantics and been prefixed. See http://goo.gl/U9mE5.
            end = start + BYTES_PER_CHUNK;
            if(end > SIZE)
                end = SIZE;
            
            if ('mozSlice' in blob) 
                chunkObj["chunk"] = blob.mozSlice(start, end);
                chunkObj["id"] = chunkId;
             else 
                // var chunk = blob.webkitSlice(start, end);
                chunkObj["chunk"] = blob.slice(start, end);
                chunkObj["start"] = start;
                chunkObj["end"] = end-1;
                chunkObj["id"] = chunkId;
            
            chunkId++;
            item.chunks.push(chunkObj);

            start = end ;
        
        this.upload(item, location, SIZE, isresume);
    ,

    upload: function(item, location, SIZE, isresume) 
        var xhr = new XMLHttpRequest();
        // Upload the first chunk
        xhr.upload.addEventListener("error", this.onFileUploadError.createDelegate(this, [item, xhr], 0), false);
        xhr.onload = this.getStatus.createDelegate(this, [item, xhr, isresume], 0);
        xhr.onreadystatechange = this.isChunkUploaded.createDelegate(this, [item, item.chunks[0], xhr, 0, SIZE, location, isresume], 0);
        xhr.open("PUT", location, true);
        xhr.setRequestHeader("Content-Range", "bytes " + item.chunks[0].start + "-" + item.chunks[0].end + "/" + SIZE);
        xhr.send(item.chunks[0].chunk);
    ,

    uploadNext: function(item, xhr, index, SIZE, location, isresume) 
        if(index > item.chunks.length) 
            return;
        

        console.log("uploading next chunk");

        xhr = new XMLHttpRequest();
        xhr.upload.addEventListener("error", this.onFileUploadError.createDelegate(this, [item, xhr], 0), false);
        xhr.onload = this.getStatus.createDelegate(this, [item, xhr, isresume], 0);
        xhr.onreadystatechange = this.isChunkUploaded.createDelegate(this, [item, xhr], 0);
        xhr.open("PUT", location, true);
        xhr.setRequestHeader("Content-Range", "bytes " + item.chunks[index].start + "-" + item.chunks[index].end + "/" + SIZE);
        xhr.send(item.chunks[index].chunk);
        //this.uploadNext(item, xhr, index + 1, SIZE, location, isresume);
    ,

    isChunkUploaded: function(item, chunkObj, request, index, SIZE, location, isresume, e) 
        if (request.readyState === 4) 
            console.log("chunk " + index + " uploaded");
            this.uploadNext(item, request, index + 1, SIZE, location, isresume);
        
    ,

附:我不能用 jquery 做同样的事情(不要问为什么)。

【问题讨论】:

this.getStatus 是什么?可以发布吗? 【参考方案1】:

没关系,这工作正常。我发送的函数参数作为函数参数比预期的少,因此我犯了一个错误。

【讨论】:

以上是关于在循环中使用 xhr 对象进行 html5 分块上传的主要内容,如果未能解决你的问题,请参考以下文章

使用 html5 分块上传文件

使用 JavaScript 分块下载文件

中止 xmlhttprequest

大文件 (> 500MB) 的 HTML5 可恢复和分块上传

php 下 html5 XHR2 + FormData + File API 上传文件

python大文件处理