内存耗尽发送附带pdf文件的邮件(swiftmailer设置为文件)

时间:2014-05-14 08:11:33

标签: symfony swiftmailer

我正在尝试发送附带pdf的电子邮件。 我有一个Command发送大量的电子邮件和swiftmailer配置文件假脱机但我有这个错误:

PHP Fatal error:  Allowed memory size of 134217728 bytes exhausted (tried to allocate 523800 bytes) in .....vendor/tcpdf/tcpdf.php on line 4989

我的swiftmailer配置是:

swiftmailer:
    transport: "%mailer_transport%"
    host:      "%mailer_host%"
    username:  "%mailer_user%"
    password:  "%mailer_password%"
    spool:     { type: file,  path: "%kernel.root_dir%/spool" }

我的命令是:

class EnviarJustificanteCommand extends ContainerAwareCommand {
    protected function configure()
    {
        $this
            ->setName('preinscripciones:enviar')
            ->setDescription('Enviar Justificantes')
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {   
        $em = $this->getContainer()->get('doctrine')->getEntityManager();
        $textoMailPreinscripcion = "......";
        //find alumnos
        $preinscritos = $em->getRepository('BackendAlumnosBundle:Historial')->findAlumnosEnviarJustificante();
        foreach ($preinscritos as $key => $alumno) {

            if ($alumno->getEmail() != null) {
                $message = \Swift_Message::newInstance()
                    ->setSubject('Preinscripción realizada')
                    ->setFrom(array($this->container->getParameter('fromemail.contact') => '........'))
                    ->setReplyTo($this->container->getParameter('replyto.email'))
                    ->setTo($alumno->getEmail())
                    ->setBody($textoMailPreinscripcion);

                // Create your file contents in the normal way, but don't write them to disk
                $data = $this->imprmirJustificantePreinscripcionPDF($escuela, $alumno, true);
                // Create the attachment with your data
                $attachment = \Swift_Attachment::newInstance($data, 'JustificantePreinscripcion.pdf', 'application/pdf');
                // Attach it to the message
                $message->attach($attachment);
                $this->get('mailer')->send($message);

            }
            //set flag to 0 as sent
            foreach ($alumno->getHistorial() as $key => $historial) {
                $historial->setEnviarJustificante(false);
                $em->persist($alumno);
            }
        }

        $em->flush(); 
    }
}

我不知道为什么我将swiftmailer配置为内存耗尽的类型文件。一些线索?

提前致谢!

2 个答案:

答案 0 :(得分:1)

Swift_Attachment::newInstance()接受数据作为String或实现Swift_OutputByteStream的流。

你正在使用一个String,在你的情况下,它对于内存来说太大了。 (Swift执行base64编码,这会占用更多内存)

您需要将数据作为Stream传递,从而实现增量读取。

在您的情况下,您可以通过将数据写入磁盘,然后获取文件资源句柄并将其包装在包装类中来完成此操作。

Wrapper类的一个示例是:

class AttachmentStream implements Swift_OutputByteStream
{
    protected $resource;

    public function __construct($resource)
    {
        $this->resource = $resource;
    }

    public function read($length)
    {
        $string = fread($this->resource, $length);

        if(false === $string){
            throw new Swift_IoException('Unable to read from stream');
        }

        return (0 === strlen($string)) ? false : $string;
    }

    public function setReadPointer($byteOffset)
    {
        return 0 === fseek($this->resource,$byteOffset);
    }
}

然后您可以将其称为:

...
$fp          = fopen($file,$mode);
$stream      = new AttachmentStream($fp);
$filename    = 'JustificantePreinscripcion.pdf';
$contentType = 'application/pdf';
$attach      = Swift_Attachment::newInstance($stream,$filename,$contentType);

答案 1 :(得分:-1)

在尝试生成PDF文件时,看起来它在TCPD中死亡。不太令人惊讶; TCPDF非常苛刻。试试http://knpbundles.com/KnpLabs/KnpSnappyBundle包,它使用wkhtmltopdf(http://wkhtmltopdf.org/)。应该快得多,并且不太可能遇到内存限制。