Показать PDF через вызов AJAX к API Symfony с помощью dompdf или wkhtmltopdf
Недавно мне пришлось разработать веб-сайт с Symfony и React. Одна из функций, которую я должен был сделать, заключалась в том, чтобы сгенерировать PDF-файл с помощью Symfony и вернуть его на передний план. Я нашел много руководств по dompdf или wkhtmltopdf для symfony, но ничего о том, как справиться с тем фактом, что мой фронт был не Twig, а React!
С ДомПДФ
Сначала я попробовал domPDF, очень хорошую библиотеку, если вы хотите быстро создать PDF.
Следуйте инструкциям в их гитхабе, чтобы установить его так, как вы хотите.
Тогда вот пример создания PDF-файла, который вы уже могли найти в других учебниках:
$domPdf = new Dompdf(); $html = $this->renderView('pdf/my_pdf.html.twig'); $domPdf->loadHtml($html); $domPdf->setPaper('A4', 'portrait'); $domPdf->render(); $domPdf->stream('my-pdf.pdf');
Stream создаст ответ, который будет использоваться внешним интерфейсом. Например, в JS после вызова API вы будете использовать ответ PDF:
apiCallToYourRoute.then((res) => { if (res.data) { const newBlob = new Blob([res.data], { type: 'application/pdf' }); const downloadUrl = window.URL.createObjectURL(newBlob); window.open(downloadUrl); } });
Если вы сделаете это, вы увидите PDF-файл, открывающийся в вашем браузере с… белой страницей :(
Вам просто нужно изменить одну вещь из предыдущего кода php:
$domPdf->stream('transport.pdf', [ 'compress' => false, ]);
С wkhtmltopdf
Моя вторая попытка была с wkhtmltopdf, потому что dompdf было недостаточно для того, что я хотел сделать. Например, мне нужно было использовать некоторые функции CSS 3.0. Я позволю вам провести небольшое исследование, вы найдете много плюсов и минусов в этих обеих библиотеках.
Вы можете использовать knpSnappyBundle или KnpSnappy (с бинарником). Я использовал второй метод, но не стесняйтесь делать, как хотите.
$pdf = new Pdf($rootPath.'/vendor/h4cc/wkhtmltopdf-amd64/bin/wkhtmltopdf-amd64'); $html = $this->renderView('pdf/my_pdf.html.twig'); $pdf->getOutputFromHtml($html); return new Response( $pdf->getOutputFromHtml($html), 200, array( 'Content-Type' => 'application/pdf', 'Content-Disposition' => 'inline; filename="my-pdf.pdf"', ) );
И снова у вас будет ответ, который используется интерфейсом. Тот же пример кода js:
apiCallToYourRoute.then((res) => { if (res.data) { const newBlob = new Blob([res.data], { type: 'application/pdf' }); const downloadUrl = window.URL.createObjectURL(newBlob); window.open(downloadUrl); } });
Еще раз PDF-файл будет открыт в вашем браузере с … снова белой страницей!
Как и в случае с dompdf, вам нужно добавить небольшую опцию, чтобы библиотека не сжимала возвращаемый PDF:
$this->pdf->setOptions([ 'no-pdf-compression' => true, ]);
Надеюсь, это поможет вам, и не стесняйтесь комментировать и помогать друг другу!