Показать 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, ]);
Надеюсь, это поможет вам, и не стесняйтесь комментировать и помогать друг другу!