使用 XMLHttpRequest 上传大文件时的进度条
Posted
技术标签:
【中文标题】使用 XMLHttpRequest 上传大文件时的进度条【英文标题】:Progress bar while uploading large files with XMLHttpRequest 【发布时间】:2013-04-04 15:27:08 【问题描述】:我正在尝试使用 XMLHttpRequest 和 file.slice 将一些大文件上传到服务器。 我已经在文档和其他各种链接的帮助下做到了这一点。 由于上传大文件是一项漫长的工作,我想为用户提供一个进度条。 经过更多阅读后,我遇到了example,理论上,这正是我需要的。 通过获取示例代码并使其适应我的需求,我达到了
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;
;
电话就像(没有验证)
upload.upload(document.getElementById("#upload").files[0]);
我的问题是进度事件没有触发。 我已经为进度事件尝试了 xhr.addEventListener 和 xhr.upload.addEventListener (一次和一次),但它永远不会触发。 onreadystatechange 和 load 事件触发就好了。
如果我做错了什么,我将不胜感激
更新 经过多次尝试,我设法模拟了一个进度,但我遇到了另一个问题:Chrome 的 UI 在上传期间没有更新。 现在的代码是这样的
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 + '%';
;
更新 2 我已经设法修复它并模拟了一个也适用于 chrome 的进度条。 我已经用有效的代码示例更新了之前的代码示例。 您可以通过减小一次上传的块的大小来更频繁地“刷新”栏 谢谢你的帮助
【问题讨论】:
您是否正在使用缩短document.getElementById
通话的功能?看起来这就是 $get()
正在做的事情,但我没有看到它在任何地方定义。
是的。但我不认为这是问题所在。它在加载事件中工作得很好,并将其设置为 100%
@Cioby 你能上传你的解决方案的 JSFiddle 吗?
【参考方案1】:
如https://***.com/a/3694435/460368 中所述,您可以这样做:
if(xhr.upload)
xhr.upload.onprogress=upload.updateProgress;
和
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 + '%';
【讨论】:
进度事件仍未触发; @Cioby 您是否尝试过以异步方式进行操作?xhr.open('POST', upload.pageName, true);
w3.org/TR/XMLHttpRequest/#the-open()-method
抱歉回复晚了。我已经尝试了这两种建议,但都没有成功。由于我不明白进度事件不会触发的原因。我已经用进度更新了主帖
@Cioby 你在.open('POST', uri, true)
之前附上了upload.onprocess
吗?
@Henry,感谢您的提示,将事件处理程序放在打开和发送之前使其工作。【参考方案2】:
有我的解决方案:
function addImages(id)
var files = $("#files").prop("files");
var file = files[loopGallery];
var cList = files.length;
var fd = new FormData();
fd.append("file", file);
fd.append("galerie", id);
var xhr = new XMLHttpRequest();
xhr.open("POST", "moduls/galerie/uploadimages.php", true);
xhr.upload.onprogress = function(e)
var percentComplete = Math.ceil((e.loaded / e.total) * 100);
$("#progress").css("display","");
$("#progressText").text((loopGallery+1)+" z "+cList);
$("#progressBar").css("width",percentComplete+"%");
;
xhr.onload = function()
if(this.status == 200)
$("#progressObsah").load("moduls/galerie/showimages.php?ids="+id);
if((loopGallery+1) == cList)
loopGallery = 0;
else
$("#progressBar").css("width", "0%");
loopGallery++;
addImages(id);
if(cList > 0)
xhr.send(fd);
【讨论】:
以上是关于使用 XMLHttpRequest 上传大文件时的进度条的主要内容,如果未能解决你的问题,请参考以下文章