为什么php://输入拒绝我的大文件上传?

时间:2015-06-10 13:17:12

标签: php ajax symfony file-upload

我一直在颠倒互联网,以便为我的Symfony2应用程序提供分块大文件上传。为了简化操作,我将测试程序与我的应用程序的其余部分分开。它唯一的作用是尝试测试php://输入是否可以使用本文中描述的方法接受我的大文件上传:

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);
}

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

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

xhr.open(“POST”,url,false); 使用我自己的localhost网址。我也在这里尝试过。不同之处在于,如果我们在第三个参数中有false,它可以处理小文件。

使用async true它似乎只给两个文件原始myfile.tmp,我fopen和一个0kb文件重命名为。 “filename.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"

1 个答案:

答案 0 :(得分:0)

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

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