2009-05-20 2 views
5

Мое PHP-приложение имеет API, который может получать достаточно большие файлы (до 32 МБ), которые кодируются base64. Цель состоит в том, чтобы записать эти файлы где-нибудь в моей файловой системе. Конечно, декодировано. Каким будет наименее ресурсоемкий способ сделать это?Как base64-декодировать большие файлы в PHP

Редактировать: Получение файлов через API означает, что у меня есть 32 МБ строка в моем приложении PHP, а не 32 МБ исходного файла где-то на диске. Мне нужно, чтобы эта строка была декодирована в файловую систему.

Используя собственный base64_decode РНР() не разрезая его, потому что он использует много памяти, так что я продолжать работать в ограничение по памяти в PHP (я знаю, я мог бы поднять этот предел, но я не чувствую себя хорошо о разрешении PHP для использования 256 МБ или около того для каждого процесса).

Любые другие варианты? Могу ли я сделать это вручную? Или записать файл на диск, закодированный и вызвать некоторую внешнюю команду? Любая мысль?

ответ

20

Даже если это принятый ответ, у меня есть другое предложение.

Если вы извлекаете данные из API, вы не должны хранить всю полезную нагрузку в переменной. Используя завиток или другие сборщики HTTP, вы можете автоматически сохранять свои данные в файле.

Предполагая, что вы выборки данных с помощью простого GET 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); 

Преимущества:

  • Должно быть быстрее (меньше копирования огромных переменных)
  • очень мало накладных расходов памяти

Если вы должны захватить данные из временной переменной, я могу предложить t такой подход:

$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

Хорошая идея, но не то, что я ищу. В моем случае клиентские приложения подталкивают большие файлы по XML-RPC (HTTP POST) к моему серверу (наряду с несколькими другими параметрами). Клиенты могут находиться за NAT и брандмауэрами, поэтому получение данных от клиента с помощью GET невозможно. –

+0

Если структура ответа xml rpc несколько статична, вы можете вручную пройти через тело ответа, так что вы все равно можете полностью избежать использования памяти. Если вы должны поместить данные во временную переменную, вы можете немного изменить настройку. (Я обновляю пример сразу после примера;)) – Evert

+0

Спасибо за обновление. Я считаю, что он превосходит тот ответ, который я изначально принял. –

11

Декодировать данные в небольших кусках. Четыре символа данных Base64 равны трем байтам данных «Base256».

Так что вы можете группу каждые 1024 символов и декодировать их до 768 октетов двоичных данных:

$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

Спасибо. Прежде всего я отмечаю это как принятое: в моем первоначальном вопросе я упоминаю, что исходный файл поступает через API. Итак, это переменная (строка 32 МБ) в PHP, а не файл, который вы читаете. Есть ли что-то, что я могу использовать вместо вашего fread(), который возвращает мне куски строки эффективно? То есть не создавая слишком много дубликатов копий, которые поглощают память? –

+0

Вы можете читать с входа через 'php: // input'. См. Http://docs.php.net/manual/en/wrappers.php.php – Gumbo

Смежные вопросы