file_get_contents大文件上传

时间:2014-12-15 19:53:16

标签: php

我正在尝试使用fsockopen上传大于2gb的大文件。但是对于file_get_content,出现以下错误,我无法将大文件存储在内存中。我需要以块的形式发送数据,但无法弄清楚我将如何执行此操作。请有人能指导我吗?

  

致命错误:允许的内存大小为134217728字节耗尽(尝试分配727826869字节)

    $file_info =  finfo_open(FILEINFO_MIME);  
    $mime_type = finfo_file($file_info, $file_loc); 
    $file = file_get_contents($file_loc);

    $fp = fsockopen($host, 80, $errno, $errstr, 30);
    if ($fp) {
        $out = "POST /upload/".basename($url)." HTTP/1.1\r\n";
        $out .= "Host: ".$host."\r\n";
        $out .= "Accept-Language: en-US,en;q=0.8\r\n";
        $out .= "Content-Type: ".$mime_type."\r\n";
        $out .= 'Content-Length: ' . filesize($file_loc) . "\r\n";
        $out .= "Content-Disposition: attachment; filename=\"".urlencode(basename($file_loc))."\"\r\n\r\n";

        fwrite($fp, $out);
        fwrite($fp, $file);
        $response = '';
        while (!feof($fp)) {
            $response .= fgets($fp, 128);
        }
        fclose($fp);

3 个答案:

答案 0 :(得分:3)

file_get_contents将整个文件的内容作为变量返回。在你的情况下,这意味着它将尝试创建2GB变量,耗尽允许的内存。

尝试使用fopenfgets。这将允许您以较小的块处理文件。

$file_info =  finfo_open(FILEINFO_MIME);  
$mime_type = finfo_file($file_info, $file_loc); 
$fileHandle = fopen($file_loc);

$fp = fsockopen($host, 80, $errno, $errstr, 30);
if ($fp) {
    $out = "POST /upload/".basename($url)." HTTP/1.1\r\n";
    $out .= "Host: ".$host."\r\n";
    $out .= "Accept-Language: en-US,en;q=0.8\r\n";
    $out .= "Content-Type: ".$mime_type."\r\n";
    $out .= 'Content-Length: ' . filesize($file_loc) . "\r\n";
    $out .= "Content-Disposition: attachment; filename=\"".urlencode(basename($file_loc))."\"\r\n\r\n";

    fwrite($fp, $out);
    while(!feof($fileHandle)){
        fwrite($fp, fgets($fileHandle, 1024));
    }
    fclose($fileHandle);

    $response = '';
    while (!feof($fp)) {
        $response .= fgets($fp, 128);
    }
    fclose($fp);

答案 1 :(得分:1)

file_get_contents()将返回指定url /文件的内容并将该数据返回到您的变量中。这意味着如果您正在下载10gig文件,那么您需要在PHP中使用10gig内存限制(加上开销)。

对于一个简单的剧本而言,这是一个荒谬的公羊。您应该使用流式系统来下载那么多数据。例如。使用byte-serving以较小的块来获取url,或使用curl将其直接写入文件。

答案 2 :(得分:0)

尝试使用fopenfread

以块的形式阅读文件
function readFileChunked($filename) {
    $chunksize = 512 ; // bytes per chunk
    $handle = fopen($filename, "rb");

    if ($handle === false)
        return false;        

    while (!feof($handle)) {
        print fread($handle, $chunksize);            
        ob_flush();
        flush();
    }

    return  fclose($handle);
}