2011-01-25 8 views
14

Mam skrypt PHP, który czasami musi zapisywać duże pliki na dysku. Jeżeli plik jest wystarczająco duży (w tym przypadku około 2 MB), to w skrypcie PHP zabraknie pamięci (PHP Błąd krytyczny: Dozwolony rozmiar pamięci ######## wyczerpanych bajtów). Wiem, że mogłem po prostu zwiększyć limit pamięci, ale to nie wydaje się być dla mnie pełnym rozwiązaniem - musi być lepszy sposób, prawda?Jaki jest najlepszy sposób na zapisanie dużego pliku na dysk w PHP?

Jaki jest najlepszy sposób na zapisanie dużego pliku na dysk w PHP?

+1

Jakie jest źródło tych danych? Poza tym większość konfiguracji PHP powinna obsługiwać 2MB bez problemu. Twój limit pamięci może być poniżej. – webbiedave

+1

Skąd pochodzi plik? Jeśli już istnieje na dysku, najodpowiedniejsze byłoby "copy()". – mario

+0

W tym przypadku otrzymuję plik ze zdalnego serwera za pomocą zwijania. Tak, mam to w zmiennej. –

Odpowiedz

15

Musisz plik tymczasowy, w którym można umieścić bity od pliku źródłowego oraz co do być dołączone:

$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'); 

ten sposób, cała zawartość source nie są wczytywane do pamięci. Podczas korzystania z cURL, można pominąć ustawianie CURLOPT_RETURNTRANSFER i zamiast tego dodać bufor wyjściowy, który zapisuje do pliku tymczasowego:

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); 

Wydaje się, że ja zawsze tęsknię oczywiste. Jak zauważył Marc, istnieje CURLOPT_FILE, aby bezpośrednio zapisać odpowiedź na dysk.

+0

To ma sens, ale w tym przypadku pobrałem plik z innego serwera za pomocą curl, więc jest już w pamięci. –

+0

@Joe I zaktualizowałem odpowiedź. Kolejna sugestia na ciebie. –

+0

dla pierwszego rozwiązania, które mogłeś użyć ['stream_copy_to_stream'] (http://php.net/stream_copy_to_stream) też ;-) – arnaud576875

1

Linia piśmie przez linię (lub pakietu przez pakietu w przypadku plików binarnych) przy użyciu funkcji takich jak fwrite()

0

Spróbuj this answer:

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

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

    fclose($file); 
Powiązane problemy