【问题标题】:Why is php://input rejecting my large file uploads?为什么 php://input 拒绝我的大文件上传?
【发布时间】:2015-06-10 13:17:11
【问题描述】:

我一直在颠倒互联网,以便让分块的大文件上传为我的 Symfony2 应用程序工作。为了简化事情,我将测试程序与我的应用程序的其余部分分开。它唯一做的就是尝试用本文描述的方法测试 php://input 是否可以接受我的大文件上传:

http://www.webiny.com/blog/2012/05/07/webiny-file-upload-with-html5-and-ajax-using-php-streams/

我的理解是,如果用户上传 2GB+ 的大型视频文件,那么服务器上将占用 2GB+ 的 RAM,并且文章中的方法将其减少到每个并发上传者的 4096 位。 (我不确定如何在 localhost 服务器上测试 RAM 使用情况)

但是,当我尝试上传大文件时,浏览器只需等待一两秒,然后发布一个 1kb 的视频文件。

我为 php.ini 设置了较高的值。

这是PHP代码的相关部分:

     public function lastoppAction(Request $request)
{

    $videofilename = (string)$request->request->get("filnavn");
    $inputHandler = fopen("php://input", "rb");
    $fileHandler = fopen("videoer\\myfile.tmp", "wb") or die('fopen failed');;

    while(true) {
$buffer = fgets($inputHandler, 4096);
if (strlen($buffer) == 0) {

    fclose($inputHandler);
    fclose($fileHandler);
            break;
}
fwrite($fileHandler, $buffer) or die('fwrite failed');;
    }
     $url = $this->generateUrl('largefile_navngi', array('filnavn' => $videofilename));
     return $this->redirect($url);
}
public function navngiAction(Request $request)
{
        $filnavn = $request->query->get('filnavn');
        $sti = $this->container->getParameter('kernel.root_dir');
        $websti = preg_replace('/app/','web',$sti,1);
        print_r("Filnavn: " . $filnavn);
        rename($websti . "/videoer/myfile.tmp",$websti . "/videoer/" . $filnavn);
        $url = $this->generateUrl('largefile_index');
        return $this->redirect($url);
}

重定向的原因是为了重命名正确接收文件名变量。

AJAX 代码类似于上面链接的文章,但有以下区别:

xhr.open("POST", url, false); 使用我自己的 localhost 网址。我也在这里尝试过 true 。不同之处在于,如果我们在第三个参数中设置为 false,它适用于小文件。

使用 async true 似乎只给两个文件我打开到的原始 myfile.tmp 和一个它重命名的 0kb 文件。 “文件名.mp4”。

奇怪的是,当ajax代码运行时:

xhr.onreadystatechange = function()
                {
                    if(xhr.readyState == 4)
                    {
                        if(xhr.status == 200)
                        {
                            //alert("success");// process success
                                                            alert("Filnavn: " + filnavn);
                        }else{
                            // process error
                                                            alert("Status: " + xhr.status);
                        }
                    }
                };

即使 16 MB 这样的小文件在没有其他问题的情况下完全上传,状态也会变为 500。

这是树枝文件:

    <h1>Test av å laste opp større filer</h1>
    <form method="post" action="{{path('largefile_lastopp')}}">
        <label>Fil: </label>
        <input type="file" name="fil" id="video" /><br /><br />
         <input type="hidden" name="filnavn" id="filnavn" />
         <input type="hidden" name="mimetype" id="mimetype" />

        <input onclick="upload('video',0)" type="submit" name="submit" />

    </form>
     ::1 - - [10/Jun/2015:15:41:36 +0200] "POST /LargeFileUpload/web/app_dev.php/lastopp HTTP/1.1" 302 436 "http://localhost/LargeFileUpload/web/app_dev.php/" "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36"

【问题讨论】:

  • 可能服务器配置为低于所需大小的MAX POST SIZE
  • 我认为您在文章中将标准文件上传与另一种方式混合在一起。看文章html。完全不同
  • 我有一个很大的 MAX POST SIZE
  • 你已经配置了upload_max_filesize ?
  • @Paulius S.upload_max_filesize=2000M

标签: php ajax symfony file-upload


【解决方案1】:

我认为这里的问题是客户端代码一次读取整个文件,然后从中创建一个 blob。如果您尝试上传 1GB 的文件,这意味着浏览器需要至少 2GB 的 RAM 才能发送第一个字节。

我可以想象可能存在防止这种内存(ab-)使用的安全措施。

【讨论】:

  • 感谢您提供的信息。如果安全措施正在阻止某些事情,我发现没有错误消息很奇怪。如果是这种情况,我是否可以在某种日志文件中找到错误消息或使用不同的错误设置?
  • 不确定;取决于浏览器和客户端操作系统。我会尝试在客户端代码中添加一些日志语句(或断点,如果您有具有调试功能的浏览器),以查看那里发生了什么。
  • 建议的代码很难做到这一点。您将不得不发送多个请求,并且服务器必须以正确的顺序重建这些片段。据我所知,FileReader API 不支持部分读取文件。
猜你喜欢
  • 2013-11-10
  • 1970-01-01
  • 1970-01-01
  • 2018-11-29
  • 2015-12-06
  • 2016-01-05
  • 1970-01-01
  • 2013-08-08
  • 2014-10-31
相关资源
最近更新 更多