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
相关产品推荐
相关产品推荐

