Каков наилучший способ записи большого файла на диск в PHP? - PullRequest
14 голосов
/ 25 января 2011

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

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

Ответы [ 3 ]

15 голосов
/ 25 января 2011

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

$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's 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 для прямой записи ответа на диск.

1 голос
/ 25 января 2011

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

0 голосов
/ 04 ноября 2015

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

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

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

    fclose($file);
...