You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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文件流的返回类型冲突。

解决方案

按照如下步骤修改即可正常实现下载:

  1. 修改自定义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;
    }
}
  1. 优化控制器返回格式(可选,建议修改)
    不要直接调用$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;
}
  1. 清理缓存
    修改完成后执行php bin/console cache:clear清理OroPlatform缓存,重新测试即可正常触发下载。

内容的提问来源于stack exchange,提问作者Louis Bertin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 10:36:02