OroPlatform网格行自定义动作实现PDF下载时返回错误问题咨询
上下文
我目前正在开发一个OroPlatform项目,需要为OroPlatform网格添加文件下载的自定义动作,已经完成的开发内容如下:
# datagrids.yml business-unit-grid: properties: getpdf_link: type: url route: baltimore_action_pdf params: - id actions: getpdf: type: getpdf label: "Export garanties" data_identifier: u.id entity_name: Oro\Bundle\OrganizationBundle\Entity\BusinessUnit icon: file link: getpdf_link
<?php namespace Baltimore\Bundle\AppBundle\Extension\Action\Actions; use Oro\Bundle\DataGridBundle\Extension\Action\Actions\AjaxAction; class GetPdfAction extends AjaxAction { /** * @var array */ protected $requiredOptions = ['entity_name', 'data_identifier']; public function getOptions() { $options = parent::getOptions(); $options['frontend_type'] = 'getpdf'; if (empty($options['frontend_handle'])) { $options['frontend_handle'] = 'getpdf'; } return $options; } }
<?php namespace Baltimore\Bundle\AppBundle\Controller\Actions; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; use Dompdf\Dompdf; use Dompdf\Options; /** * @Route("/action") */ class ActionController extends Controller { /** * @Route("/pdfexport/{id}", requirements={"id"="\d+"}, name="baltimore_action_pdf", methods={"GET", "POST"}) */ public function actionPdf(Request $request) { //dump($request->get('id')); $pdfOptions = new Options(); $pdfOptions->set('defaultFont', 'Arial'); // 实例化Dompdf $dompdf = new Dompdf($pdfOptions); // 加载twig渲染的HTML $html = $this->renderView('BaltimoreAppBundle:pdf:mypdf.html.twig', [ 'title' => "Welcome to our PDF Test" ]); $dompdf->loadHtml($html); $dompdf->setPaper('A4', 'portrait'); $dompdf->render(); // 输出PDF强制下载 $dompdf->stream("mypdf.pdf", [ "Attachment" => true ]); exit; } }
为了排除控制器本身代码问题,我编写了普通控制器的相同逻辑,运行正常:
/** * @Route("/download", name="app_vehicule_download") */ public function downloadAction() { $pdfOptions = new Options(); $pdfOptions->set('defaultFont', 'Arial'); $dompdf = new Dompdf($pdfOptions); $html = $this->renderView('BaltimoreAppBundle:pdf:mypdf.html.twig', [ 'title' => "Welcome to our PDF Test" ]); $dompdf->loadHtml($html); $dompdf->setPaper('A4', 'portrait'); $dompdf->render(); $dompdf->stream("mypdf.pdf", [ "Attachment" => true ]); exit; }
问题描述
现有逻辑整体运行正常,网格中已经显示自定义按钮,接口也可以正常返回JSON响应,但实现PDF下载功能时就会报错。
相同代码放在普通控制器中可正常运行,根本原因是继承的AjaxAction对应的前端逻辑默认以AJAX请求调用接口,要求返回JSON格式响应,和PDF文件流的返回类型冲突。
解决方案
按照如下步骤修改即可正常实现下载:
- 修改自定义Action的父类
将GetPdfAction的父类从AjaxAction改为NavigateAction,NavigateAction的逻辑是点击后直接跳转至对应URL,不会发起AJAX请求,适配文件下载场景:
<?php namespace Baltimore\Bundle\AppBundle\Extension\Action\Actions; // 替换导入的父类 use Oro\Bundle\DataGridBundle\Extension\Action\Actions\NavigateAction; class GetPdfAction extends NavigateAction { /** * @var array */ protected $requiredOptions = ['entity_name', 'data_identifier']; public function getOptions() { $options = parent::getOptions(); $options['frontend_type'] = 'getpdf'; // 不需要自定义frontend_handle,直接用父类的navigate逻辑即可 return $options; } }
- 优化控制器返回格式(可选,建议修改)
不要直接调用$dompdf->stream()后exit,改为返回Symfony标准的Response对象,避免框架层的输出拦截问题:
/** * @Route("/pdfexport/{id}", requirements={"id"="\d+"}, name="baltimore_action_pdf", methods={"GET"}) */ public function actionPdf(Request $request, int $id) { $pdfOptions = new Options(); $pdfOptions->set('defaultFont', 'Arial'); $dompdf = new Dompdf($pdfOptions); $html = $this->renderView('BaltimoreAppBundle:pdf:mypdf.html.twig', [ 'title' => "Welcome to our PDF Test", // 可以在这里传入$id对应的业务数据 ]); $dompdf->loadHtml($html); $dompdf->setPaper('A4', 'portrait'); $dompdf->render(); $pdfContent = $dompdf->output(); $response = new \Symfony\Component\HttpFoundation\Response($pdfContent); $response->headers->set('Content-Type', 'application/pdf'); $response->headers->set('Content-Disposition', $response->headers->makeDisposition( \Symfony\Component\HttpFoundation\ResponseHeaderBag::DISPOSITION_ATTACHMENT, 'mypdf.pdf' )); return $response; }
- 清理缓存
修改完成后执行php bin/console cache:clear清理OroPlatform缓存,重新测试即可正常触发下载。
内容的提问来源于stack exchange,提问作者Louis Bertin
相关产品推荐
相关产品推荐

