2016-02-23 11 views
7

Mam poniższy kod do wyjścia duży plik, ale to przewróceniem ponieważ użycie pamięci PHP wydaje się rosnąć i rozwijać się jako plik jest czytany:Jak wyjście ogromny plik z PHP bez wyczerpaniu pamięci

<?php 
    // various header() calls etc. 
    $stream = fopen($tarfile,'r'); 
    ob_end_flush(); 
    while (!feof($stream)) { 
    $buf = fread($stream, 4096); 
    print $buf; 
    flush(); 
    unset($buf); 
    $aa_usage = memory_get_usage(TRUE); // ← this keeps going up! 
    } 
    fclose($stream); 

Pomyślałem, że dzięki kombinacji spłukiwania i unsetu dodatkowe użycie pamięci będzie ograniczone do bufora 4k, ale wyraźnie się mylę.

+1

Dlaczego nie wystarczy użyć [readfile()] (http: //www.php .net/manual/en/function.readfile.php)? –

+0

Spróbuj 'ob_flush();' i 'flush();' razem. – SparK

+0

Jeśli chcesz go wyprowadzić, możesz użyć jego treści, możesz użyć 'require_once 'filename.php';' - http://php.net/manual/en/function.require-once.php – KDOT

Odpowiedz

4

Jeśli wszystko, czego potrzebujesz, to wyprowadzanie zawartości pliku, to właściwym narzędziem do tego celu jest funkcja PHP readfile(). Wymienić cały kod wysłana z:

readfile($tarfile); 

Jako documentation mówi:

Uwaga:

readfile() nie przedstawi żadnych problemów z pamięcią, nawet podczas wysyłania dużych plików, na jego posiadać. Jeśli wystąpi błąd braku pamięci, upewnij się, że buforowanie wyjściowe jest wyłączone z ob_get_level().

+0

Dzięki. Czasami tęsknisz za oczywistymi rzeczami, co ?! Chociaż nadal chciałbym zrozumieć, co jest nie tak z powyższym kodem. – artfulrobot

+0

Uruchomiłem twój kod, a wartość '$ aa_usage' nie zmienia się. To jest '2097152' na PHP 7,' 786432' na PHP 5.3 i '262144' na PHP 5.4, 5.5 i 5.6. Użyłem pliku 43 MB do testowania z gołym CLI PHP. – axiac

+0

hmmm, interesujące, dzięki. Moim celem jest Drupal 7, chociaż myślałem, że wyłączyłem buforowanie za pomocą wywołania ob_end_clean() ... Tajemnicze! – artfulrobot

0

Można próbować ładować tylko tyle danych, ile trzeba najpierw, a jeśli załadować więcej danych należy użyć funkcji: fseek()

+0

to właśnie robi kod - ładuje 4KB na raz. (nie ma potrzeby fseek - odbywa się to automatycznie w ramach odczytu) Wydaje się, że PHP utrzymuje go dłużej niż potrzebuję, więc każdy odczyt zwiększa wykorzystanie pamięci. – artfulrobot

Powiązane problemy