生成了 Symfony4 PDF 但有一个 HTTP500

Symfony4 PDF is generated but there is a HTTP500

我正在生成一个 pdf,该文件已生成,但由于我进行了作曲家更新(从 symfony 4.2.4 到 4.2.5),出现以下错误

The file 'generated/pdf/Mon_Beau_Chateau_Roi_Des_Fôrets_Su-Per_04-2019_8ddb3a64c4.pdf' was not created (command: /var/www/html/gestImmo/bin/wkhtml2pdf --lowquality '/tmp/knp_snappy5ca4ac7a32b3d7.26041529.html' 'generated/pdf/Mon_Beau_Chateau_Roi_Des_Frets_Su-Per_04-2019_8ddb3a64c4.pdf').

我看了日志,没找到问题所在:

[2019-04-03 14:52:10] snappy.INFO: Generate from file(s) "/tmp/knp_snappy5ca4ac7a32b3d7.26041529.html" to file "generated/pdf/Mon_Beau_Chateau_Roi_Des_Fôrets_Su-Per_04-2019_8ddb3a64c4.pdf". {"command":"/var/www/html/gestImmo/bin/wkhtml2pdf --lowquality '/tmp/knp_snappy5ca4ac7a32b3d7.26041529.html' 'generated/pdf/Mon_Beau_Chateau_Roi_Des_Frets_Su-Per_04-2019_8ddb3a64c4.pdf'","env":null,"timeout":false} []
[2019-04-03 14:52:10] snappy.ERROR: An error happened while generating "generated/pdf/Mon_Beau_Chateau_Roi_Des_Fôrets_Su-Per_04-2019_8ddb3a64c4.pdf". {"command":"/var/www/html/gestImmo/bin/wkhtml2pdf --lowquality '/tmp/knp_snappy5ca4ac7a32b3d7.26041529.html' 'generated/pdf/Mon_Beau_Chateau_Roi_Des_Frets_Su-Per_04-2019_8ddb3a64c4.pdf'","status":0,"stdout":"QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-www-data'\nlibpng warning: iCCP: known incorrect sRGB profile\nlibpng warning: iCCP: known incorrect sRGB profile\nLoading page (1/2)\n[>                                                           ] 0%\r[==============================>                             ] 50%\rWarning: Failed to load file:///build/runtime.js (ignore)         \nWarning: Failed to load file:///build/app.js (ignore)\n[============================================================] 100%\rPrinting pages (2/2)                                               \n[>                                                           ] \rDone                                                           \n","stderr":""} []
[2019-04-03 14:52:10] request.CRITICAL: Uncaught PHP Exception RuntimeException: "The file 'generated/pdf/Mon_Beau_Chateau_Roi_Des_Fôrets_Su-Per_04-2019_8ddb3a64c4.pdf' was not created (command: /var/www/html/gestImmo/bin/wkhtml2pdf --lowquality '/tmp/knp_snappy5ca4ac7a32b3d7.26041529.html' 'generated/pdf/Mon_Beau_Chateau_Roi_Des_Frets_Su-Per_04-2019_8ddb3a64c4.pdf')." at /var/www/html/gestImmo/vendor/knplabs/knp-snappy/src/Knp/Snappy/AbstractGenerator.php line 350 {"exception":"[object] (RuntimeException(code: 0): The file 'generated/pdf/Mon_Beau_Chateau_Roi_Des_Fôrets_Su-Per_04-2019_8ddb3a64c4.pdf' was not created (command: /var/www/html/gestImmo/bin/wkhtml2pdf --lowquality '/tmp/knp_snappy5ca4ac7a32b3d7.26041529.html' 'generated/pdf/Mon_Beau_Chateau_Roi_Des_Frets_Su-Per_04-2019_8ddb3a64c4.pdf'). at /var/www/html/gestImmo/vendor/knplabs/knp-snappy/src/Knp/Snappy/AbstractGenerator.php:350)"} []

这是控制器

/**
     * @Route("/{id}/paid", name="rent_release_paid", methods={"GET"})
     * @param RentRelease $rentRelease
     * @param PdfGenerator $pdfGenerator
     * @param MonthlyMailer $monthlyMailer
     * @return Response
     */
    public function rentIsPaid(
        RentRelease $rentRelease,
        PdfGenerator $pdfGenerator,
        MonthlyMailer $monthlyMailer
    ): Response {
        if (!$this->isGranted('EDIT_RENT_RELEASE', $rentRelease)) {
            $this->addFlash('danger', 'Vous n\'etes pas autorisé à effectuer cette action.');

            return $this->redirectToRoute('rent_release_index');
        }

        $rentRelease->setStatus('Payé');

        $entityManager = $this->getDoctrine()->getManager();
        $entityManager->persist($rentRelease);
        $entityManager->flush();

        $pdfGenerator->generateRentReleasePdf($rentRelease); //I call the service here
        $monthlyMailer->sendRentReleaseToLessees($rentRelease);

        return $this->redirectToRoute(
            'rent_release_pdf_delete',
            ['id' => $rentRelease->getId()]
        );
     }

这是我的服务:

 /**
     * @param RentRelease $rentRelease
     * @throws \Twig\Error\LoaderError
     * @throws \Twig\Error\RuntimeError
     * @throws \Twig\Error\SyntaxError
     */
    public function generateRentReleasePdf(RentRelease $rentRelease)
    {
        $currentDate = new \DateTime();
        $currentDate = $currentDate->format('m-Y');

        if ($rentRelease->getStatus() === 'Payé') {
            $propertyName = $rentRelease->getPropertyName();
            $propertyName= str_replace(' ', '_', $propertyName);


            $lesseeName = str_replace(' ', '-', $rentRelease->getLesseeName());
            $fileName = $propertyName . '_' . $lesseeName . '_' . date("m-Y") . '_';
            $fileName = $fileName . bin2hex(random_bytes(5)) . '.pdf';

            $html = $this->twig->render('rent_release/pdf.html.twig', [
                'rent_release' => $rentRelease,
                'current_date' => $currentDate,
            ]);


            $this->knpSnappyPdf->generateFromHtml("$html", "generated/pdf/$fileName"); // on the Stack Trace, the problem is here

            $rentRelease->setPdf($fileName);
            $this->manager->persist($rentRelease);
            $this->manager->flush();
        }
    }

有人知道吗?

好的,问题是因为我选择的名字有特殊字符

所以我在我的服务中添加了一个私有函数,我不知道有什么最干净的方法:

/**
 * Created by PhpStorm.
 * User: thocou
 * Date: 12/03/19
 * Time: 15:50
 */

namespace App\Service;

use App\Entity\RentRelease;
use DateTime;
use Doctrine\Common\Persistence\ObjectManager;
use Knp\Snappy\Pdf;
use Twig_Environment;

class PdfGenerator
{
    /**
     * @var Pdf
     */
    private $knpSnappyPdf;

    /**
     * @var Twig_Environment
     */
    private $twig;

    /**
     * @var ObjectManager
     */
    private $manager;

    /**
     * PdfGenerator constructor.
     * @param Pdf $knpSnappyPdf
     * @param Twig_Environment $twig
     * @param ObjectManager $manager
     */
    public function __construct(Pdf $knpSnappyPdf, Twig_Environment $twig, ObjectManager $manager)
    {
        $this->knpSnappyPdf = $knpSnappyPdf;
        $this->twig = $twig;
        $this->manager = $manager;
    }

    /**
     * Replacing accents in a string
     * @param $string
     * @return string
     */
    private function removeAccents($string)
    {
        if (!preg_match('/[\x80-\xff]/', $string)) {
            return $string;
        }

        $chars = array(
            // Decompositions for Latin-1 Supplement
            chr(195).chr(128) => 'A', chr(195).chr(129) => 'A',
            chr(195).chr(130) => 'A', chr(195).chr(131) => 'A',
            chr(195).chr(132) => 'A', chr(195).chr(133) => 'A',
            chr(195).chr(135) => 'C', chr(195).chr(136) => 'E',
            chr(195).chr(137) => 'E', chr(195).chr(138) => 'E',
            chr(195).chr(139) => 'E', chr(195).chr(140) => 'I',
            chr(195).chr(141) => 'I', chr(195).chr(142) => 'I',
            chr(195).chr(143) => 'I', chr(195).chr(145) => 'N',
            chr(195).chr(146) => 'O', chr(195).chr(147) => 'O',
            chr(195).chr(148) => 'O', chr(195).chr(149) => 'O',
            chr(195).chr(150) => 'O', chr(195).chr(153) => 'U',
            chr(195).chr(154) => 'U', chr(195).chr(155) => 'U',
            chr(195).chr(156) => 'U', chr(195).chr(157) => 'Y',
            chr(195).chr(159) => 's', chr(195).chr(160) => 'a',
            chr(195).chr(161) => 'a', chr(195).chr(162) => 'a',
            chr(195).chr(163) => 'a', chr(195).chr(164) => 'a',
            chr(195).chr(165) => 'a', chr(195).chr(167) => 'c',
            chr(195).chr(168) => 'e', chr(195).chr(169) => 'e',
            chr(195).chr(170) => 'e', chr(195).chr(171) => 'e',
            chr(195).chr(172) => 'i', chr(195).chr(173) => 'i',
            chr(195).chr(174) => 'i', chr(195).chr(175) => 'i',
            chr(195).chr(177) => 'n', chr(195).chr(178) => 'o',
            chr(195).chr(179) => 'o', chr(195).chr(180) => 'o',
            chr(195).chr(181) => 'o', chr(195).chr(182) => 'o',
            chr(195).chr(182) => 'o', chr(195).chr(185) => 'u',
            chr(195).chr(186) => 'u', chr(195).chr(187) => 'u',
            chr(195).chr(188) => 'u', chr(195).chr(189) => 'y',
            chr(195).chr(191) => 'y',
            // Decompositions for Latin Extended-A
            chr(196).chr(128) => 'A', chr(196).chr(129) => 'a',
            chr(196).chr(130) => 'A', chr(196).chr(131) => 'a',
            chr(196).chr(132) => 'A', chr(196).chr(133) => 'a',
            chr(196).chr(134) => 'C', chr(196).chr(135) => 'c',
            chr(196).chr(136) => 'C', chr(196).chr(137) => 'c',
            chr(196).chr(138) => 'C', chr(196).chr(139) => 'c',
            chr(196).chr(140) => 'C', chr(196).chr(141) => 'c',
            chr(196).chr(142) => 'D', chr(196).chr(143) => 'd',
            chr(196).chr(144) => 'D', chr(196).chr(145) => 'd',
            chr(196).chr(146) => 'E', chr(196).chr(147) => 'e',
            chr(196).chr(148) => 'E', chr(196).chr(149) => 'e',
            chr(196).chr(150) => 'E', chr(196).chr(151) => 'e',
            chr(196).chr(152) => 'E', chr(196).chr(153) => 'e',
            chr(196).chr(154) => 'E', chr(196).chr(155) => 'e',
            chr(196).chr(156) => 'G', chr(196).chr(157) => 'g',
            chr(196).chr(158) => 'G', chr(196).chr(159) => 'g',
            chr(196).chr(160) => 'G', chr(196).chr(161) => 'g',
            chr(196).chr(162) => 'G', chr(196).chr(163) => 'g',
            chr(196).chr(164) => 'H', chr(196).chr(165) => 'h',
            chr(196).chr(166) => 'H', chr(196).chr(167) => 'h',
            chr(196).chr(168) => 'I', chr(196).chr(169) => 'i',
            chr(196).chr(170) => 'I', chr(196).chr(171) => 'i',
            chr(196).chr(172) => 'I', chr(196).chr(173) => 'i',
            chr(196).chr(174) => 'I', chr(196).chr(175) => 'i',
            chr(196).chr(176) => 'I', chr(196).chr(177) => 'i',
            chr(196).chr(178) => 'IJ',chr(196).chr(179) => 'ij',
            chr(196).chr(180) => 'J', chr(196).chr(181) => 'j',
            chr(196).chr(182) => 'K', chr(196).chr(183) => 'k',
            chr(196).chr(184) => 'k', chr(196).chr(185) => 'L',
            chr(196).chr(186) => 'l', chr(196).chr(187) => 'L',
            chr(196).chr(188) => 'l', chr(196).chr(189) => 'L',
            chr(196).chr(190) => 'l', chr(196).chr(191) => 'L',
            chr(197).chr(128) => 'l', chr(197).chr(129) => 'L',
            chr(197).chr(130) => 'l', chr(197).chr(131) => 'N',
            chr(197).chr(132) => 'n', chr(197).chr(133) => 'N',
            chr(197).chr(134) => 'n', chr(197).chr(135) => 'N',
            chr(197).chr(136) => 'n', chr(197).chr(137) => 'N',
            chr(197).chr(138) => 'n', chr(197).chr(139) => 'N',
            chr(197).chr(140) => 'O', chr(197).chr(141) => 'o',
            chr(197).chr(142) => 'O', chr(197).chr(143) => 'o',
            chr(197).chr(144) => 'O', chr(197).chr(145) => 'o',
            chr(197).chr(146) => 'OE',chr(197).chr(147) => 'oe',
            chr(197).chr(148) => 'R',chr(197).chr(149) => 'r',
            chr(197).chr(150) => 'R',chr(197).chr(151) => 'r',
            chr(197).chr(152) => 'R',chr(197).chr(153) => 'r',
            chr(197).chr(154) => 'S',chr(197).chr(155) => 's',
            chr(197).chr(156) => 'S',chr(197).chr(157) => 's',
            chr(197).chr(158) => 'S',chr(197).chr(159) => 's',
            chr(197).chr(160) => 'S', chr(197).chr(161) => 's',
            chr(197).chr(162) => 'T', chr(197).chr(163) => 't',
            chr(197).chr(164) => 'T', chr(197).chr(165) => 't',
            chr(197).chr(166) => 'T', chr(197).chr(167) => 't',
            chr(197).chr(168) => 'U', chr(197).chr(169) => 'u',
            chr(197).chr(170) => 'U', chr(197).chr(171) => 'u',
            chr(197).chr(172) => 'U', chr(197).chr(173) => 'u',
            chr(197).chr(174) => 'U', chr(197).chr(175) => 'u',
            chr(197).chr(176) => 'U', chr(197).chr(177) => 'u',
            chr(197).chr(178) => 'U', chr(197).chr(179) => 'u',
            chr(197).chr(180) => 'W', chr(197).chr(181) => 'w',
            chr(197).chr(182) => 'Y', chr(197).chr(183) => 'y',
            chr(197).chr(184) => 'Y', chr(197).chr(185) => 'Z',
            chr(197).chr(186) => 'z', chr(197).chr(187) => 'Z',
            chr(197).chr(188) => 'z', chr(197).chr(189) => 'Z',
            chr(197).chr(190) => 'z', chr(197).chr(191) => 's'
        );

        $string = strtr($string, $chars);

        return $string;
    }

    /**
     * @param RentRelease $rentRelease
     * @throws \Twig\Error\LoaderError
     * @throws \Twig\Error\RuntimeError
     * @throws \Twig\Error\SyntaxError
     * @throws \Exception
     */
    public function generateRentReleasePdf(RentRelease $rentRelease)
    {
        $currentDate = new DateTime();
        $currentDate = $currentDate->format('m-Y');

        if ($rentRelease->getStatus() === 'Payé') {
            $propertyName = $rentRelease->getPropertyName();
            $propertyName= str_replace(' ', '_', $propertyName);

            $lesseeName = str_replace(' ', '-', $rentRelease->getLesseeName());
            $fileName = $propertyName . '_' . $lesseeName . '_' . date("m-Y") . '_';
            $fileName = $this->removeAccents($fileName);
            $fileName = $fileName . bin2hex(random_bytes(5)) . '.pdf';

            $html = $this->twig->render('rent_release/pdf.html.twig', [
                'rent_release' => $rentRelease,
                'current_date' => $currentDate,
            ]);

            $this->knpSnappyPdf->generateFromHtml("$html", "generated/pdf/$fileName");

            $rentRelease->setPdf($fileName);
            $this->manager->persist($rentRelease);
            $this->manager->flush();
        }
    }
}