使用XMLHttpRequest上传大文件时的进度条 [英] Progress bar while uploading large files with XMLHttpRequest

查看:504
本文介绍了使用XMLHttpRequest上传大文件时的进度条的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图使用XMLHttpRequest和file.slice将一些大文件上传到服务器。

我在文档和其他各种链接的帮助下管理这些事情。

由于上传大文件是一项长期的工作,我想为用户提供一个进度条。

在我读过一些理论上,我需要的。

通过获取示例代码并将其调整为我的需要,我达到了

pre $ var $ upload
{
blobs:[],
pageName:'',
bytesPerChunk:20 * 1024 * 1024,
currentChunk:0,
loaded:0,
total:0,
file:null,
fileName:,
$ b $ uploadChunk:function(blob,fileName,fileType){
var xhr =新的XMLHttpRequest();

xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.responseText){
// alert(xhr .responseText);
}
}
};

xhr.addEventListener(load,function(evt){
$(#dvProgressPrcent)。html(100%);
$ get('dvProgress ').style.width ='100%';
},false);

xhr.addEventListener(progress,function(evt){
if(evt.lengthComputable){
var progress = Math.ceil(((upload.loaded + evt (进度+%);
$ get('dvProgress')。style.width =进度+'%';
}
},false);

xhr.upload.addEventListener(progress,function(evt){
if(evt.lengthComputable){
var progress = Math.ceil(((upload.loaded + evt.loaded)/ upload.total)* 100);
$(#dvProgressPrcent)。html(progress +%);
$ get('dvProgress')。style.width = progress +'%';
}
},false);

xhr.open('POST',upload.pageName,false);

xhr.setRequestHeader(Content-Type,multipart / form-data);
xhr.setRequestHeader(X-File-Name,fileName);
xhr.setRequestHeader(X-File-Type,fileType);
xhr.send(blob);
},
上传:函数(文件){
var start = 0;
var end = 0;
var size = file.size;

var date = new Date();
upload.fileName = date.format(dd.MM.yyyy_HH.mm.ss)+_+ file.name;

upload.loaded = 0;
upload.total = file.size;

while(start< size){
end = start + upload.bytesPerChunk;
if(end> size){
end = size;
}

var blob = file.slice(start,end);
upload.uploadChunk(blob,upload.fileName,file.type);
start = end;
upload.loaded + = start;
}

return upload.fileName;
}
};

这个调用就像(没有验证)

  upload.upload(的document.getElementById( #上传)文件[0]); 

我的问题是progress事件不会触发。

我已经尝试了xhr.addEventListener和xhr.upload.addEventListener(每次一次,两次一次)进度事件,但它从不触发。 onreadystatechange和load事件触发器就好。



我非常感谢帮助我做错了什么?



更新

经过多次尝试,我已经设法模拟一个进度,但是我遇到了另一个问题:Chrome的UI在上传过程中没有更新。
$

  var upload = 
{
pageName:'',b $ b代码看起来像这样
bytesPerChunk:20 * 1024 * 1024,
已加载:0,
合计:0,
文件:null,
文件名:,

uploadFile:function(){
var size = upload.file.size;

if(upload.loaded> size)return;

var end = upload.loaded + upload.bytesPerChunk;
if(end> size){end = size; }

var blob = upload.file.slice(upload.loaded,end);

var xhr = new XMLHttpRequest();

xhr.open('POST',upload.pageName,false);

xhr.setRequestHeader(Content-Type,multipart / form-data);
xhr.setRequestHeader(X-File-Name,upload.fileName);
xhr.setRequestHeader(X-File-Type,upload.file.type);

xhr.send(blob);

upload.loaded + = upload.bytesPerChunk;

setTimeout(upload.updateProgress,100);
setTimeout(upload.uploadFile,100);
},
上传:函数(文件){
upload.file =文件;

var date = new Date();
upload.fileName = date.format(dd.MM.yyyy_HH.mm.ss)+_+ file.name;

upload.loaded = 0;
upload.total = file.size;

setTimeout(upload.uploadFile,100);


return upload.fileName;
},
updateProgress:function(){
var progress = Math.ceil(((upload.loaded)/ upload.total)* 100);
if(progress> 100)progress = 100;

$(#dvProgressPrcent)。html(progress +%);
$ get('dvProgress')。style.width = progress +'%';
}
};



更新2

我已经设法解决这个问题,并且模拟了一个在chrome中工作的进度条。
我更新了以前的代码示例。

您可以通过减少一次上传的块的大小来更频繁地进行刷新。
帮助您获得帮助

解决方案

https://stackoverflow.com/a/3694435/460368 中所述,您可以执行:

  if(xhr.upload)
xhr.upload.onprogress = upload.updateProgress;

 <$ (evt.lengthComputable){
var progress = Math.ceil(((upload.loaded + evt.loaded)/ upload) .total)* 100);
$(#dvProgressPrcent)。html(progress +%);
$ get('dvProgress')。style.width = progress +'%';
}
}


I am trying to upload some large files to the server using XMLHttpRequest and file.slice.
I've manage doing this with the help of documentations and other various links.
Since uploading large file is a lengthily job, i would like to provide the user with a progress bar.
After some more readings i've come across on an example that, theoretically, does exactly what i need.
By taking the sample code and adapting it to my needs i reached

var upload =
{
blobs: [],
pageName: '',
bytesPerChunk: 20 * 1024 * 1024,
currentChunk: 0,
loaded: 0,
total: 0,
file: null,
fileName: "",

uploadChunk: function (blob, fileName, fileType) {
    var xhr = new XMLHttpRequest();

    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
            if (xhr.responseText) {
                // alert(xhr.responseText);
            }
        }
    };

    xhr.addEventListener("load", function (evt) {
        $("#dvProgressPrcent").html("100%");
        $get('dvProgress').style.width = '100%';
    }, false);

    xhr.addEventListener("progress", function (evt) {
        if (evt.lengthComputable) {
            var progress = Math.ceil(((upload.loaded + evt.loaded) / upload.total) * 100);
            $("#dvProgressPrcent").html(progress + "%");
            $get('dvProgress').style.width = progress + '%';
        }
    }, false);

    xhr.upload.addEventListener("progress", function (evt) {
        if (evt.lengthComputable) {
            var progress = Math.ceil(((upload.loaded + evt.loaded) / upload.total) * 100);
            $("#dvProgressPrcent").html(progress + "%");
            $get('dvProgress').style.width = progress + '%';
        }
    }, false);

    xhr.open('POST', upload.pageName, false);

    xhr.setRequestHeader("Content-Type", "multipart/form-data");
    xhr.setRequestHeader("X-File-Name", fileName);
    xhr.setRequestHeader("X-File-Type", fileType);
    xhr.send(blob);
},
upload: function (file) {
    var start = 0;
    var end = 0;
    var size = file.size;

    var date = new Date();
    upload.fileName = date.format("dd.MM.yyyy_HH.mm.ss") + "_" + file.name;

    upload.loaded = 0;
    upload.total = file.size;

    while (start < size) {
        end = start + upload.bytesPerChunk;
        if (end > size) {
            end = size;
        }

        var blob = file.slice(start, end);
        upload.uploadChunk(blob, upload.fileName, file.type);
        start = end;
        upload.loaded += start;
    }

    return upload.fileName;
}
};

The call is like (without the validations)

upload.upload(document.getElementById("#upload").files[0]);

My problem is that the progress event doesn't trigger.
I've tried xhr.addEventListener and with xhr.upload.addEventListener (each at a time and both at a time) for the progress event but it never triggers. The onreadystatechange and load events trigger just fine.

I would greatly appreciate help with what i am doing wrong

Update
After many attempts i've manage to simulate a progress but i've ran into another problem: Chrome's UI is not updating during the upload.
The code looks like this now

var upload =
{
    pageName: '',
    bytesPerChunk: 20 * 1024 * 1024,
    loaded: 0,
    total: 0,
    file: null,
    fileName: "",

    uploadFile: function () {
        var size = upload.file.size;

        if (upload.loaded > size) return;

        var end = upload.loaded + upload.bytesPerChunk;
        if (end > size) { end = size; }

        var blob = upload.file.slice(upload.loaded, end);

        var xhr = new XMLHttpRequest();

        xhr.open('POST', upload.pageName, false);

        xhr.setRequestHeader("Content-Type", "multipart/form-data");
        xhr.setRequestHeader("X-File-Name", upload.fileName);
        xhr.setRequestHeader("X-File-Type", upload.file.type);

        xhr.send(blob);

        upload.loaded += upload.bytesPerChunk;

        setTimeout(upload.updateProgress, 100);
        setTimeout(upload.uploadFile, 100);
    },
    upload: function (file) {
        upload.file = file;

        var date = new Date();
        upload.fileName = date.format("dd.MM.yyyy_HH.mm.ss") + "_" + file.name;

        upload.loaded = 0;
        upload.total = file.size;

        setTimeout(upload.uploadFile, 100);


        return upload.fileName;
    },
    updateProgress: function () {
        var progress = Math.ceil(((upload.loaded) / upload.total) * 100);
        if (progress > 100) progress = 100;

        $("#dvProgressPrcent").html(progress + "%");
        $get('dvProgress').style.width = progress + '%';
    }
};


Update 2
I've managed to fix it and simulate a progress bar that works in chrome too.
i've updated previous code sample with the one that works.
You can make the bar 'refresh' more often by reducing the size of the chunk uploaded at a time Tahnk you for your help

解决方案

As stated in https://stackoverflow.com/a/3694435/460368, you could do :

if(xhr.upload)
     xhr.upload.onprogress=upload.updateProgress;

and

updateProgress: function updateProgress(evt) 
{
   if (evt.lengthComputable) {
       var progress = Math.ceil(((upload.loaded + evt.loaded) / upload.total) * 100);
       $("#dvProgressPrcent").html(progress + "%");
       $get('dvProgress').style.width = progress + '%';
   }
}

这篇关于使用XMLHttpRequest上传大文件时的进度条的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆