如何在不使用太多内存的情况下强制下载大文件?

Lea*_*ves 9 php apache memory-management codeigniter force-download

我正在尝试向用户提供大型zip文件.当有2个并发连接时,服务器内存不足(RAM).我将内存量从300MB增加到4GB(Dreamhost VPS)然后它工作正常.

我需要允许超过2个并发连接.实际的4GB将允许20个并发连接(太糟糕).

好吧,我正在使用的当前代码需要内存的两倍,然后是实际的文件大小.这太糟糕了.我希望将文件"流式传输"给用户.所以我分配的不仅仅是为用户提供的块.

以下代码是我在CodeIgniter(PHP框架)中使用的代码:

ini_set('memory_limit', '300M'); // it was the maximum amount of memory from my server
set_time_limit(0); // to avoid the connection being terminated by the server when serving bad connection downloads
force_download("download.zip", file_get_contents("../downloads/big_file_80M.zip"));exit;
Run Code Online (Sandbox Code Playgroud)

force_download函数如下(CodeIgniter默认帮助函数):

function force_download($filename = '', $data = '')
{
    if ($filename == '' OR $data == '')
    {
        return FALSE;
    }

    // Try to determine if the filename includes a file extension.
    // We need it in order to set the MIME type
    if (FALSE === strpos($filename, '.'))
    {
        return FALSE;
    }

    // Grab the file extension
    $x = explode('.', $filename);
    $extension = end($x);

    // Load the mime types
    @include(APPPATH.'config/mimes'.EXT);

    // Set a default mime if we can't find it
    if ( ! isset($mimes[$extension]))
    {
        $mime = 'application/octet-stream';
    }
    else
    {
        $mime = (is_array($mimes[$extension])) ? $mimes[$extension][0] : $mimes[$extension];
    }

    // Generate the server headers
    if (strpos($_SERVER['HTTP_USER_AGENT'], "MSIE") !== FALSE)
    {
        header('Content-Type: "'.$mime.'"');
        header('Content-Disposition: attachment; filename="'.$filename.'"');
        header('Expires: 0');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header("Content-Transfer-Encoding: binary");
        header('Pragma: public');
        header("Content-Length: ".strlen($data));
    }
    else
    {
        header('Content-Type: "'.$mime.'"');
        header('Content-Disposition: attachment; filename="'.$filename.'"');
        header("Content-Transfer-Encoding: binary");
        header('Expires: 0');
        header('Pragma: no-cache');
        header("Content-Length: ".strlen($data));
    }

    exit($data);
}
Run Code Online (Sandbox Code Playgroud)

我尝试了一些我在Google中找到的基于块的代码,但文件总是被破坏了.可能是因为代码不好.

谁能帮助我?

Kin*_*pus 3

这个线程中有一些想法。我不知道 readfile() 方法是否会节省内存,但这听起来很有希望。

  • 我原本以为“readfile”或“fpassthru”也可以工作,但今天遇到了一个问题,“readfile”实际上仍然将整个文件读取到内存中。也许这在新版本的 PHP 中已经改变了(我使用的是 5.2)。 (2认同)