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

Symfony StreamedResponse下载正常但日志报request.CRITICAL错误

问题:StreamedResponse导出CSV时触发LogicException错误

我实现了以下导出CSV的控制器方法,功能正常,点击下载按钮能获取文件,但dev.log中一直出现严重错误:

public function download(
        string $id,
        ChannelRepository $channelRepository,
        CustomerNewsletterRepository $customerNewsletterRepository
    ): Response
    {
        $channel = $channelRepository->find($id);
        $customerNewsletters = $customerNewsletterRepository->findAllIterable($channel);

        set_time_limit(3600);
        ob_flush();

        $response = new StreamedResponse();
        $response->headers->set('X-Accel-Buffering', 'no');
        $disposition = HeaderUtils::makeDisposition(
            HeaderUtils::DISPOSITION_ATTACHMENT,
            'export.csv'
        );
        $response->headers->set('Content-Disposition', $disposition);
        $response->setCallback(function () use ($customerNewsletters): void {
            $fp = fopen('php://output', 'w');
            fputcsv($fp, ['Email', 'Date'], ';');
            /** @var CustomerNewsletter $customerNewsletter */
            foreach ($customerNewsletters as $customerNewsletter) {
                fputcsv($fp, [
                    $customerNewsletter->getEmail(),
                    $customerNewsletter->getCreatedAt()->format('d/m/y H:i'),
                ], ';');
                flush();
            }
            fclose($fp);
        });

        return $response->send();
    }

错误日志内容:

grep "CRITI" dev.log

[2023-07-07T11:35:23.192510+00:00] request.CRITICAL: Uncaught PHP Exception LogicException: "The content cannot be set on a StreamedResponse instance." at website/vendor/symfony/http-foundation/StreamedResponse.php line 124 {"exception":"[object] (LogicException(code: 0): The content cannot be set on a StreamedResponse instance. at website/vendor/symfony/http-foundation/StreamedResponse.php:124)"} []

请问如何避免该错误?


解决方案

错误原因

你在控制器中手动调用了$response->send(),但Symfony的控制器规范是返回Response对象,由框架内核统一处理响应发送。当你自行调用send()后,内核后续仍会尝试对该Response执行设置content的操作,而StreamedResponse不允许设置content,因此抛出这个异常。

修复步骤

将控制器最后一行的return $response->send();修改为return $response;即可解决问题。

修改后的完整代码:

public function download(
        string $id,
        ChannelRepository $channelRepository,
        CustomerNewsletterRepository $customerNewsletterRepository
    ): Response
    {
        $channel = $channelRepository->find($id);
        $customerNewsletters = $customerNewsletterRepository->findAllIterable($channel);

        set_time_limit(3600);
        ob_flush();

        $response = new StreamedResponse();
        $response->headers->set('X-Accel-Buffering', 'no');
        $disposition = HeaderUtils::makeDisposition(
            HeaderUtils::DISPOSITION_ATTACHMENT,
            'export.csv'
        );
        $response->headers->set('Content-Disposition', $disposition);
        $response->setCallback(function () use ($customerNewsletters): void {
            $fp = fopen('php://output', 'w');
            fputcsv($fp, ['Email', 'Date'], ';');
            /** @var CustomerNewsletter $customerNewsletter */
            foreach ($customerNewsletters as $customerNewsletter) {
                fputcsv($fp, [
                    $customerNewsletter->getEmail(),
                    $customerNewsletter->getCreatedAt()->format('d/m/y H:i'),
                ], ';');
                flush();
            }
            fclose($fp);
        });

        return $response;
    }

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 17:42:27