下载ZipArchive内存不足

时间:2018-09-25 09:18:45

标签: php symfony download out-of-memory symfony4

在heroku应用程序上下载文件时遇到问题。 我有一个基本的PHP语言,允许我们有128MB的内存限制。

我的错误如下:

  

(1/1)OutOfMemoryException错误:允许的内存大小为134217728   字节已耗尽(尝试分配77709312字节)

好的,我明白了,但是奇怪的是77709312bytes只有74MB。

那怎么了? 这是我的下载操作的代码:

/**
 * @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;
}

3 个答案:

答案 0 :(得分:1)

  

(1/1)OutOfMemoryException错误:耗尽了134217728字节的允许的内存大小(试图分配77709312字节)

当时,php过程尝试分配已分配内存的77709312字节,可以使用memory_get_usage()函数进行检查。您的情况必须大于(134217728-77709312 =)56508416字节。

如果在创建zip文件的过程中引发了异常,则可以尝试使用外部工具来创建zip文件。像

  

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

否则,尝试找出引发此异常的确切时间,以尝试释放所有不必要的已用内存。

答案 1 :(得分:0)

file_get_contents会将文件加载到内存中,当我将其放入Response对象中时,这将有效地将所有内容从内存复制到输出缓冲区。这就是为什么74MB附近的存档会由于双重工作而导致Out of memory出现128M配置(74 * 2)错误的原因。

目前,我无法使用readfile()来解决此问题,因为行为对于我的需求而言有太多不同。但是readfile()将打开并输出到缓冲区,而无需使用两次内存。

编辑:我找到的最好的选择是通过使用Symfony 3.2的BinaryFileResponse对象有效地处理响应流。

答案 2 :(得分:-1)

您尝试过file_get_contents($zipName); unlink($zipName);以便从本地删除文件