Как предотвратить, чтобы mcrypt_encrypt () не смог зашифровать файл большего размера?

Я пытаюсь зашифровать загруженный файл с помощью сценария PHP, аналогичного этот. Он отлично работает с небольшими файлами, но когда я пытаюсь загрузить тестовый файл размером 49,2 МБ (который не так велик по сегодняшним меркам), из-за следующего моя php-страница отображает пустую страницу, завершая сценарий:

$binaryFileData = file_get_contents($serverFilePath);
$binaryEncFile = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $binaryKey, $binaryFileData, MCRYPT_MODE_CBC, $binaryIV);

Я получаю строку в error_log файл, который говорит:

Неустранимая ошибка PHP: допустимый объем памяти 134217728 байт исчерпан
(пытался выделить 51694736 байт) в
/home2/myaccount/public_html/myfldr/myfile.inc в строке 620

Линия 620 указывает на mcrypt_encrypt в моем примере выше.

Поэтому я провел небольшое исследование, и люди предложили добавить следующее к php.ini файл:

memory_limit = -1

Что я и сделал, но это все равно привело к тому же результату.

Итак, у меня есть вопрос из двух частей:

  1. Очевидно, как предотвратить прерывание сценария этим исключением?

  2. Есть ли способ заставить эту функцию возвращать ошибку или выдавать исключение, которое я могу перехватить, вместо того, чтобы просто завершить (и в результате пользователю будет показана белая / пустая страница?)

Мне нужно решить пункт 2 выше также, чтобы иметь возможность удалить незашифрованный файл с сервера в случае сбоя шифрования (что, очевидно, я не могу сделать, если mcrypt_encrypt просто завершает мой сценарий.

PS. Я должен сказать, что я запускаю этот скрипт на общей учетной записи, размещенной в BlueHost.

0

Решение

использование

ini_set(“memory_limit”,”640M“);

Чтобы установить предел памяти на более высокий предел.
Вышеупомянутое увеличивает предел с 128 МБ до 640 МБ.

Если вы все еще сталкиваетесь с проблемами, используйте

realpath_cache_size = 16k
realpath_cache_ttl = 120

Обратите внимание, что в php 5.3 и позже вы можете просто поместить файл user.ini (со строкой memory_limit = 640M) в каталог public_html, но это не разрешено всеми cpanels.

1

Другие решения

Одним из возможных путей решения этой проблемы является шифрование файла небольшими порциями (например, 4128 байт за раз).

Образец кода:

$fr=fopen('input.file','r');
$fw=fopen('output.file','w');
while(!feof($fr))
{
$buffer=fread($fr,4128);
$result=mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $binaryKey, $buffer, MCRYPT_MODE_CBC, $binaryIV);
false!==$result && fwrite($fw,$result);
}
fclose($fw);
fclose($fr);

Таким образом, вы получите зашифрованный файл, который позже можно будет расшифровать, выполнив эти шаги в обратном порядке.

Обратите внимание, что размер куска 4128 выбран не случайно. Зная, что RIJNDAEL поддерживает блоки размером 128/192/256 бит (т.е. 16/24/32 байта), я определил LCM между этими числами (то есть 96), а затем я выбрал любой размер фрагмента (около 4K), кратный 96 Так получилось, что 4128 соответствовали критериям.

Почему размер куска важен? Поскольку MCrypt делит ваш входной текст на фиксированные блоки длиной вашего блока и, если есть напоминание, он дополняет это пространство нулями до тех пор, пока длина блока не разделится точно. Так что мы не хотим, чтобы MCrypt сделал это, верно? В любом случае, имейте в виду, что это будет сделано для последнего блока вашего файла (если только вам не повезло, что он уже кратен размеру вашего блока).

Я надеюсь, что это помогает…

0

По вопросам рекламы [email protected]