Как принудительно загрузить большие файлы, не используя слишком много памяти?

Я ' m пытается предоставить пользователям большие zip-файлы. Когда есть 2 одновременных подключения, серверу не хватает памяти (RAM). Я увеличил объем памяти с 300 МБ до 4 ГБ (Dreamhost VPS), и тогда все заработало.

Мне нужно разрешить более двух одновременных подключений. Фактические 4 ГБ позволят примерно 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;

Функция 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);
}

Я попробовал несколько кодов на основе фрагментов, которые нашел в Google, но файл всегда доставлялся поврежденным. Вероятно, из-за плохого кода.

Кто-нибудь может мне помочь?

9
задан YakovL 3 January 2018 в 23:48
поделиться