Каков наилучший способ записи большого файла на диск в PHP?

У меня есть PHP script, который иногда приходится писать большие файлы на диск. Используя file_put_contents(), если файл достаточно большой (в данном случае около 2 МБ), PHP скрипт исчерпывает память (PHP Fatal error: Разрешенный размер памяти ######## байт исчерпан). Я знаю, что могу просто увеличить ограничение памяти, но это не похоже на полное решение для меня - должен быть лучший способ, верно?

Каков наилучший способ записи большого файла на диск в PHP?

Ответы

Ответ 1

Вам понадобится временный файл, в который вы помещаете бит исходного файла плюс добавление:

$sp = fopen('source', 'r');
$op = fopen('tempfile', 'w');

while (!feof($sp)) {
   $buffer = fread($sp, 512);  // use a buffer of 512 bytes
   fwrite($op, $buffer);
}

// append new data
fwrite($op, $new_data);    

// close handles
fclose($op);
fclose($sp);

// make temporary file the new source
rename('tempfile', 'source');

Таким образом, содержимое source не читается в памяти. При использовании cURL вы можете опустить параметр CURLOPT_RETURNTRANSFER и вместо этого добавить буфер вывода, который записывается во временный файл:

function write_temp($buffer) {
     global $handle;
     fwrite($handle, $buffer);
     return '';   // return EMPTY string, so nothing internally buffered
}

$handle = fopen('tempfile', 'w');
ob_start('write_temp');

$curl_handle = curl_init('http://example.com/');
curl_setopt($curl_handle, CURLOPT_BUFFERSIZE, 512);
curl_exec($curl_handle);

ob_end_clean();
fclose($handle);

Кажется, я всегда пропускаю очевидное. Как указал Марк, там CURLOPT_FILE можно непосредственно написать ответ на диск.

Ответ 2

Запись строк за строкой (или пакет за пакет в случае двоичных файлов) с использованием таких функций, как fwrite()

Ответ 3

Попробуйте этот ответ:

    $file   = fopen("file.json", "w");

    $pieces = str_split($content, 1024 * 4);
    foreach ($pieces as $piece) {
        fwrite($file, $piece, strlen($piece));
    }

    fclose($file);