【问题标题】:Delay after uploading large files with Jquery BlueImp uploader使用 Jquery BlueImp 上传器上传大文件后延迟
【发布时间】:2017-08-30 09:23:30
【问题描述】:

我能够通过 BlueImp Jquery Uploader 插件成功上传大文件(测试最大为 8GB)。

我的 PHP 设置是:

upload_max_filesize 8192M
post_max_size 8192M
max_execution_time 200
max_input_time 200
memory_limit 8192M

我遇到的问题是,当大文件(2gb 或更大)完成上传时,进度条会挂在 100% 上,并且需要相当长的时间才能“完成”。 除了将文件块拼凑在一起之外,我不确定正在发生什么后处理。

我已经尝试调整 UploadHandler.php 文件中的块大小,当增加(例如从 10mb 到 500mb 块)时,它似乎略有改善,但延迟仍然存在。完全禁用分块上传 (0) 似乎没有任何改进,我也不确定这样做的潜在后果。

对于 2gb 文件,延迟时间约为 20 秒,但对于 4gb 文件,延迟时间约为 2 分钟。一个 7gb 的文件大约需要 3-4 分钟,有时会超时。这让用户等待,不知道发生了什么,因为此时进度条已完成 100%。

有没有人知道这可能是什么,或者如何解决它?我怀疑 /tmp 中的文件可能被复制而不是移动,但据我所知,php 文件中没有任何迹象。

提升我的服务器 VM 上的 CPU 和 RAM 会稍微改善一些情况,但在此过程中运行“top”命令表明 CPU 和 RAM 似乎并没有被大量耗尽(0-2%,而 90-实际上传期间为 100%)。

非常感谢。

【问题讨论】:

  • 上传过程 浏览器将 2gig 发送给 Apache,Apache 将 2gig 传递给 PHP,您的代码运行一个 move_uploaded_file() 并将 2gig 从一个目录移动到另一个目录。至少最后一部分将在上传完成后发生
  • 感谢您的回复。上传过程本身非常快,问题是在上传“完成”之后。 “移动文件”操作会立即在命令行上发生。那么在上传后实际发生了什么导致这种延迟?

标签: php jquery file-upload blueimp


【解决方案1】:

我不是很了解,我在google上搜索了一些,我想它可能对你有帮助。

当服务器或客户端发生异常时,通常会触发“onError”事件。在上述情况下,除非服务器本身没有超时,否则不会引发异常。

一种可能性是监控上传状态并在上传事件中设置 JavaScript 超时或计数器,在达到时间限制后取消上传。

此处显示所有上传状态和错误代码 - http://help.infragistics.com/NetAdvantage/jQuery/2013.1/CLR4.0?page=igUpload_Using_Client_Side_Events.html

您可以在上传事件中使用“fileStatus”参数监控这些。

对您有帮助的链接

  1. Link1
  2. Link2
  3. Link3

【讨论】:

    【解决方案2】:

    这可能是什么

    jQuery FileUpload 注册请求进度事件。这是浏览器向服务器发送数据时的事件,而不是来自服务器的确认事件。浏览器发送和服务器确认接收之间存在延迟。有关这两个事件,请参阅Can onprogress functionality be added to jQuery.ajax() by using xhrFields?。但是,我无法为我解决此问题并使用了变通方法,因此我无法完全确认此假设。

    如何进行故障排除

    使用浏览器的调试工具并在代码中设置断点以了解可用的变量: https://github.com/blueimp/jQuery-File-Upload/blob/master/js/jquery.fileupload.js#L372

    一旦您确定要查看的内容,最好使用 console.log 打印信息并检查浏览器的控制台输出。

    解决方法

    如果您只想查看是否所有下载都已完成并向用户显示仍在进行的操作,您可能需要查看停止/完成事件,或者 fileupload('active'),请参见此处: Finish of Multiple file upload

    【讨论】:

      【解决方案3】:

      在对这个问题进行了多次故障排除和调试之后,我找到了我认为的原因,以及更好的解决方法/解决方案。这有点“hacky”(我是一个业余开发者!),所以我愿意接受任何改进它的建议,尽管它似乎对我有用。

      从客户端上传的文件实际上是上传到服务器上的这个临时位置: /tmp/systemd-private-随机数-httpd.service-随机数/tmp/sess_php-session-ID

      在客户端完成上传后,UI 进度条会达到 100%,并在服务器处理文件时保持不变。

      服务器端的处理涉及将文件从上述 /tmp 位置移动(复制,然后删除)到相关的 blueimp 位置。 (假设“user_dirs”在 blueimp 选项中启用/为真,默认目标为:/var/www/html/server/php/files/php-session-id/)。

      此复制过程可能会花费大量时间,尤其是对于大于 2gb 左右的文件。一旦服务器处理完成,blueimp 就会触发“fileuploaddone”回调,并且 UI 会更新到完成状态。

      我的目标是在这一点上提供一些交互式 UI 反馈(而不是像其他解决方法那样挂在 90%)。我的环境能够进行非常大的上传(10gb+),所以我认为不提供任何可能需要几分钟文件处理的用户反馈是不可接受的(用户认为网站已经崩溃,并关闭浏览器等) .).

      我的解决方法:

      我遇到的第一个问题是,当文件上传在客户端完成并且服务器处理开始时,似乎没有 blueimp 回调。所以我通过创建一个函数(在 main.js 中)来解决这个问题,在 data.loaded 与 data.total 匹配后显示我的自定义“处理 div”:

      $('#fileupload').bind('fileuploadprogressall', function (e, data) { console.log(data); 
      if (data.loaded == data.total) { 
      setTimeout(function(){
      $("#processwarn").fadeTo(300, 1);
      },3000);
      }})
      

      位于进度条信息下方的自定义 div 是另一个 php 页面,它每隔几秒刷新一次(使用 ajax.load),并计算当前会话上传文件夹中所有文件的总文件大小(目录总大小似乎没有提供准确的结果):

      // Calculate size of files being processed
      $filePath = "/var/www/html/server/php/files/*php-session-id*/";
      
      $total = 0;
      $d = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($filePath), 
        RecursiveIteratorIterator::SELF_FIRST
      );
      
      foreach($d as $file){
        $total += $file->getSize();
      }
      
      // Convert to readable format
      if ($total >= 1073741824)
      {
          $total = number_format($total / 1073741824, 2) . ' GB';
      }
      elseif ($total >= 1048576)
      {
          $total = number_format($total / 1048576, 2) . ' MB';
      }
      elseif ($total >= 1024)
      {
          $total = number_format($total / 1024, 2) . ' KB';
      }
      elseif ($total > 1)
      {
          $total = $total . ' bytes';
      }
      elseif ($total == 1)
      {
          $total = $total . ' byte';
      }
      else
      {
          $total = '0 bytes';
      }
      
      // Display spinner gif and size of file currently being processed
      echo "<img src=\"img/spinner.gif\" height=\"20px\" width=\"20px\">&nbsp;&nbsp;Please wait, processing files: &nbsp;&nbsp;$total";
      

      结果如下所示:

      编辑:(经过更多工作)- 添加了引导进度条:

      从测试中发现的附加点:

      启用分块(例如设置为 1gb (maxChunkSize: 1000000000) )后,问题几乎消失了,因为处理时间对用户来说似乎大大减少了,因为“复制”处理发生在分块点(每 1gb在这个例子中)。 当最终处理发生时,服务器只需“重新分块”/复制最后剩余的 1gb。
      因此,我也经历了更快的整体上传时间。 事后看来,这对许多人来说可能是一个更简单/更有效的解决方案。

      【讨论】:

        猜你喜欢
        • 2020-04-20
        • 1970-01-01
        • 1970-01-01
        • 2019-01-26
        • 2016-08-23
        • 2013-02-13
        • 2012-03-23
        • 2016-07-25
        • 2017-04-14
        相关资源
        最近更新 更多