Скачать ZipArchive OutOfMemory

У меня проблема при загрузке файла в моем приложении heroku. У меня есть базовый ini PHP, который позволяет нам иметь 128 МБ для ограничения памяти.

Моя ошибка выглядит следующим образом:

(1/1) OutOfMemoryException Error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 77709312 bytes)

Хорошо, я понял, но странно то, что 77709312bytes всего 74 МБ.

Так что не так?

Это код моего действия загрузки:

/**
 * @Route("/templates/{id}/download", name = "api_templates_download", requirements = {"id" = "\d+"})
 * @Method({"GET"})
 * @param \Symfony\Component\HttpFoundation\Request $request
 * @return \Symfony\Component\HttpFoundation\Response
 * @throws \Exception
 */
public function downloadTemplate(Request $request)
{
    $id = $request->get('id');

    try {
        $template = $this->service->getTemplate($id, $this->helper->getUser());
        $archive = $this->service->downloadTemplate($template);
        $response = new Response(file_get_contents($archive));
        $response->headers->set('Content-Type', 'application/zip');
        $response->headers->set('Content-Disposition', 'attachment;filename = "' . $archive . '"');
        $response->headers->set('Content-length', filesize($archive));

        return $response;
    } catch (\Exception $e) {
        $response = new Response(json_encode($e->getMessage()), 401);
        $response->headers->set('Content-Type', 'application/json');
        return $response;
    }
}

И метод downloadTemplate вызвал в контроллере:

/**
 * @tests Need to tests about performance - do this in September with real server
 * @param \App\Domain\Dollycast\Template\Entity\Template $template
 * @return string
 */
public function downloadTemplate(Template $template)
{
    $zip = new \ZipArchive();
    $zipName = self::ZIPDIR . $template->getName() . '.zip';

    $zip->open($zipName, \ZipArchive::CREATE);

    $finder = new Finder();
    $finder->files()->in(self::WORKDIR . $template->getName());

    $zip->addEmptyDir($template->getName());
    /** @var SplFileInfo $file */
    foreach ($finder as $file) {
        // Rename the full path to the relative Path
        $zip->addFile(
            self::WORKDIR . $template->getName() . DIRECTORY_SEPARATOR . $file->getRelativePathname(),
            $template->getName() . DIRECTORY_SEPARATOR . $file->getRelativePathname()
        );
    }

    $zip->close();

    return $zipName;
}

Я также предлагаю использовать file_get_contents ($ archive) на вашей логической стороне :)

Youssef Saoubou 25.09.2018 16:55
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
1
270
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

(1/1) OutOfMemoryException Error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 77709312 bytes)

В то время процесс php пытается выделить 77709312 байт, для которого уже выделена память, что можно проверить с помощью функции memory_get_usage (). В вашем случае это должно быть больше (134217728 - 77709312 =) 56508416 байт.

Если во время создания zip-файла возникает исключение, вы можете попробовать использовать внешний инструмент для создания zip-файла. Что-то вроде

exec("tar -zcvf archive.tar.gz /folder/tozip");

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

Не думайте, потому что у меня в архиве около 77709312 МБ. Кроме того, в сообщении об ошибке говорится не о дополнительных байтах, а об общем количестве байтов.

Greco Jonathan 25.09.2018 12:19

Процесс пытается выделить 77709312 байт, но это невозможно, потому что тогда он превысит максимум 134217728 байт, потому что в данный момент ваше приложение уже использует больше, чем (134217728 - 77709312 =) 56508416 байт.

Hubbe73 25.09.2018 12:26

Вы знаете, в какой строке произошла ошибка? При создании zip-архива или в "file_get_contents ($ archive)"?

Hubbe73 25.09.2018 13:25
Ответ принят как подходящий

file_get_contents загрузит файл в память, когда я помещу его в объект Response, это эффективно скопирует все содержимое из памяти в выходной буфер. Вот почему архив около 74MB приведет к ошибке Out of memory для конфигурации 128M (74 * 2) из-за двойной работы.

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

Обновлено: Лучшая альтернатива, которую я нашел, - это использование объекта BinaryFileResponse из Symfony 3.2, который эффективно обрабатывает поток ответов.

Вы пробовали file_get_contents($zipName); unlink($zipName);, чтобы вы могли удалить файл из локального

Привет, спасибо, но это не относится к моей проблеме, взгляните на мой ответ: p

Greco Jonathan 25.09.2018 16:50

Я знаю, что просто хотел указать на отключение, чтобы не хранить большой zip-файл :)

Youssef Saoubou 25.09.2018 16:52

Другие вопросы по теме