HTTP PUT请求 - 实现进度条

3

我发现对于上传非常大的文件(1GB或更多),HTTP PUT请求是最合适的。

这个解决方案很好,我可以将任意文件上传到服务器。然而我在监视上传进度时遇到了困难。

我已经实现了onprogress回调函数,但是它只会在通过PUT上传文件后被调用一次。

我的JavaScript代码:

var req = createRequest();
req.open("PUT", "PHP/upload_file.php?folder=" + aUploadedFile.upload_folder + "&master_folder=" + settings.strServerSideMasterFolder + "&file_name=" + aUploadedFile.file_name);
req.setRequestHeader("Content-type", "text/plain");
req.onload = function (event)
{
    console.log("OnLoad Called: " + aUploadedFile.file_name);
}
req.onprogress = function (event)
{
    console.log("OnProgress Called: " + aUploadedFile.file_name);
}
req.send(aUploadedFile.file_object);
  • 有什么方法可以监控PUT上传进度呢?
  • 我是否应该建立另一个JavaScript AJAX调用,以便监视上传到服务器的文件大小?
  • 还有其他可行的解决办法吗?

我使用:

  • HTML5
  • JavaScript
  • PHP
  • Apache

我不使用:

  • jQuery

谢谢您的帮助。


你看过这个吗?https://dev59.com/0XVD5IYBdhLWcg3wNY1Z - John Zwinck
1
@JohnZwinck:你好。感谢您的评论。我的问题可能非常具体?您的链接显示了各种进度条的实现方式,但没有一个与HTTP PUT请求相关。对于HTTP POST请求,创建进度条非常简单,但问题是相同的代码无法用于HTTP PUT请求 - Bunkai.Satori
你为什么避免使用POST? - John Zwinck
1
@JohnZwinck:在我看来,使用HTTP POST请求进行文件上传更容易,并提供了上传进度的简单实现。然而,POST请求会将整个上传的文件暂时放入服务器内存中。如果更多人上传他们的文件,则有消耗所有服务器内存的风险。除此之外,还存在困难,我无法上传超过300MB的文件,因为客户端认为上传过程已经冻结,并显示:“噢,糟糕!”我尝试了我在互联网上找到的每一个可能性,但我没有找到合适的POST请求解决方案。 - Bunkai.Satori
1个回答

4

你试过使用xhr.upload.onprogress而不是xhr.onprogress吗?

如果这个方法也不行,你可以建立另一个JavaScript AJAX调用,就像你说的那样。最近,我做了一个上传系统,每次读取文件一行,并且需要显示一些额外的上传信息,而不仅仅是百分比,所以我做了如下操作:

  • 主页面向负责处理文件的文件发出AJAX请求
  • 在那个文件中,我必须关闭连接,以便AJAX请求能够完成,但PHP脚本仍将运行,使用以下方法:
ob_start();
$file = tempnam('/tmp', uniqid()); // create a temp file to show status of the action
echo json_encode(array('file' => $file));
header('Content-length: '.ob_get_length());
header('Connection: close');
ob_end_flush();
flush(); // The AJAX request is completed here, but the script is still running...

function writeToFile($handle, $arr) {
    ftruncate($handle, 0); // empty file
    fwrite($handle, json_encode($arr));
}
$handle = fopen($file, 'w');
while (readLine($uploadedFile)) {
    // code to process line
    writeToFile($handle, array('progress' => $current / $total, 'action' => 'Reading...'));
}
// insert into database
writeToFile($handle, array('progress' => '100', 'action' => 'Inserting into database...'));
fclose($handle);
  • 在主页面,AJAX请求将返回包含信息的文件名,因此我会使用setInterval方法创建几个GET请求来访问该文件。

注意: 在我的情况下,我创建了另一个PHP文件来显示进度文件的内容(使用file_get_contents),所以当操作完成时,我可以手动删除该文件。


2
嗨,+1并感谢您的回复。你写的很有道理。回答你的问题,我没有尝试过xhr.upload.onprogress,但我会尝试一下。同时,我已经能够通过额外的AJAX调用来实现进度条。我不喜欢为每个进度条发出几百个甚至更多的AJAX调用。因此,我正在学习COMET和AJAX长轮询等主题,它们在服务器和客户端之间建立一个永久连接,并可以更精确地更新进度条。我正在学习它,所以我会看看它是否适用。 - Bunkai.Satori
3
我必须告诉你,我刚刚尝试了xhr.upload.onprogress而不是xhr.onprogress,这真的很有用。xhr.upload.onprogress效果非常好。虽然我不明白其中的区别,但非常感谢你给我的这个好建议,我将把你的答案标记为我问题的“可接受答案”。再次感谢! - Bunkai.Satori
有趣的解决方案。 - The Onin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接