所谓最佳,当然是我自己的理解,算不得数的,也想不出更确切的定语。如果改为“一种实践”不是我想要的,这不是一种选项,只用能用上,我是要复用这套实践,对个人来说没有更好的定语了。既然与我是最佳,也定会有人认同,或者阅读全文后认同,或者在若干年后认同。所以也算得上最佳吧,只是在最佳上再加上个定语更确切些:我和所有认同他是最佳实践的人们的最佳实践。循环定义了,但人对事物的理解何尝不是在循环中逐渐明晰,循环就循环了吧。
定义
动态生产文件是指即时生成pdf,excel,word,png,jpg等等,内容是实时性的,下次下载时需要重新生成。
最佳实践
- 动态生成的结果保存在临时文件中
- 使用
BinaryFileResponse
,将临时文件返回(下载)给用户 - 设置
deleteFileAfterSend()
,用户下载后临时文件被自动删除
class ReportController extends AbstractController
{
public function __invoke(ReportEngine $reportEngine): Response
{
$pdfFile = $reportEngine->generate();
return $this
->file($pdfFile, $reportEngine->buildFilename(), ResponseHeaderBag::DISPOSITION_INLINE)
->deleteFileAfterSend();
}
}
说明:
- 临时文件和用户下载的文件名无关,临时文件是随机和服务器端唯一的
-
deleteFileAfterSend()
不是100%可靠,额外的机制比如 cron 定时任务还是有必要
# 每日凌晨2点删除一天前生成的 /tmp/export-report-* 文件
0 2 * * * find /tmp/ -mtime 1 -name export-report-* -delete
分析
最佳实践使用临时文件做中转,没有使用显而易见的完全使用内存的方法。
优缺点
优点:
- 适应性广,几乎100%的文件生成库都会支持保存文件
- 文件生成库使用 Stream 等方式将内存使用降到最低
-
BinaryFileRespose
使用stream_copy_to_stream()
将文件流直接下载给客户端。 - 生成结果不占用内存,php5.3 以后支持内存回收,需要时可以及时释放,不需要等待下载完成
- 简单,顺着这条路现有的东西可直接整合
缺点:
效率问题,使用文件缓存通常会被认为效率底下。如果在现实中用能接受的效率换到上述的优点,岂不是最佳实践。真实的效率和假想的效率是两回事。
网友评论