2009-05-20 15 views
5

Moja aplikacja internetowa PHP ma API, które może odbierać rozsądnie duże pliki (do 32 MB), które są kodowane base64. Celem jest napisanie tych plików gdzieś w moim systemie plików. Oczywiście dekodowane. Jaki byłby najmniej intensywny sposób na zrobienie tego?Jak rozpakować duże pliki base64 w PHP

Edycja: Odbieranie plików za pośrednictwem interfejsu API oznacza, że ​​mam ciąg 32 MB w mojej aplikacji PHP, a nie plik źródłowy o wielkości 32 MB w innym miejscu na dysku. Muszę odszyfrować ten ciąg na system plików.

Korzystanie własne base64_decode PHP() nie jest cięcie, bo to wykorzystuje dużo z pamięci więc utrzymać prowadzenie do limitu pamięci PHP (wiem, mogłem podnieść ten limit, ale nie czuję się dobrze o umożliwienie PHP do użycia 256 MB na proces).

Jakieś inne opcje? Czy mogę zrobić to ręcznie? Lub zapisz plik na dysk zakodowany i wywołaj jakieś zewnętrzne polecenie? Jakiekolwiek myśli?

Odpowiedz

20

Nawet jeśli ma to zaakceptowane odpowiedź, mam inną propozycję.

Jeśli pobierasz dane z interfejsu API, nie przechowuj całego ładunku w zmiennej. Korzystając z curl lub innych programów pobierających HTTP, możesz automatycznie przechowywać dane w pliku.

Zakładając, że pobieranie danych za pomocą prostego URL:

$url = 'http://www.example.com/myfile.base64'; 
$target = 'localfile.data'; 

$rhandle = fopen($url,'r'); 
stream_filter_append($rhandle, 'convert.base64-decode'); 

$whandle = fopen($target,'w'); 

stream_copy_to_stream($rhandle,$whandle); 
fclose($rhandle); 
fclose($whandle); 

korzyści:

  • Powinno być szybciej (mniej kopiowanie ogromnych zmiennych)
  • Bardzo mało napowietrznych pamięci

Jeśli musisz pobrać dane ze zmiennej tymczasowej, mogę zasugerować t to podejście:

$data = 'your base64 data'; 
$target = 'localfile.data'; 

$whandle = fopen($target,'w'); 
stream_filter_append($whandle, 'convert.base64-decode',STREAM_FILTER_WRITE); 

fwrite($whandle,$data); 

fclose($whandle); 
+0

Niezły pomysł, ale nie tego, czego szukam. W moim przypadku aplikacje klienckie przesyłają duże pliki przez XML-RPC (HTTP POST) do mojego serwera (wraz z kilkoma innymi parametrami). Klienci mogą znajdować się za NAT i firewallami, więc pobieranie danych od klienta przy użyciu GET nie jest możliwe. –

+0

Jeśli struktura odpowiedzi rpc xml jest nieco statyczna, można ręcznie przejść przez treść odpowiedzi, więc nadal można całkowicie uniknąć użycia pamięci. Jeśli musisz umieścić dane w zmiennej tymczasowej, możesz nieco zmienić ustawienia. (Aktualizuję przykład zaraz po przykładzie;)) – Evert

+0

Dzięki za aktualizację. Uważam to za lepsze od odpowiedzi, którą pierwotnie zaakceptowałem. –

11

Dekoduj dane w mniejszych porcjach. Cztery znaki danych Base64 to trzy bajty danych "Base256".

więc można grupa każdy 1024 znaków i dekoduje je do 768 oktetów danych binarnych:

$chunkSize = 1024; 
$src = fopen('base64.data', 'rb'); 
$dst = fopen('binary.data', 'wb'); 
while (!feof($src)) { 
    fwrite($dst, base64_decode(fread($src, $chunkSize))); 
} 
fclose($dst); 
fclose($src); 
+0

Dzięki. Jedna rzecz, zanim zaznaczę to jako zaakceptowane: W moim pierwotnym pytaniu wspomniałem, że plik źródłowy jest dostępny za pośrednictwem interfejsu API. Jest to zmienna (ciąg 32 MB) w PHP, a nie plik, z którego czytasz. Czy jest coś, co mogę użyć zamiast Twojego fread(), który wydajnie zwraca mi kawałki kawałka? To znaczy. bez wykonywania zbyt wielu duplikatów, które pożerają pamięć? –

+0

Możesz czytać z wejścia poprzez 'php: // input'. Zobacz http://docs.php.net/manual/en/wrappers.php.php – Gumbo