Laravel邮件发送PDF附件在生产环境显示0KB无法打开问题求助
Laravel 生产环境发送PDF附件大小为0KB排查方案
- 优先排查文件读权限与路径有效性
生产环境PHP运行用户(通常为www-data、www等)对PDF文件无读权限,或open_basedir配置限制了PHP可读取的目录范围,会导致读取文件内容为空。可先执行最小验证脚本确认:
若验证失败,调整文件权限为755、所属组为PHP运行用户,或修改// 线上临时测试路由,验证后及时删除 Route::get('/test-pdf-read', function () { $testPath = '你的线上PDF绝对路径'; echo '文件是否存在:' . (file_exists($testPath) ? '是' : '否') . '<br>'; echo '文件大小:' . filesize($testPath) . 'Byte<br>'; echo '文件内容前100字符:' . substr(file_get_contents($testPath), 0, 100); });open_basedir配置将PDF存储目录加入允许列表。 - 排查异步队列场景下的文件可用性
如果邮件使用队列异步发送,会存在两类问题:- 生成PDF的Web节点与队列消费节点不是同一服务器,本地存储的PDF无法跨节点读取
- PDF生成在临时目录,队列消费时临时文件已被系统自动清理
解决方案:将PDF存储到共享存储(NAS、对象存储等),或生成文件后直接读取内容,使用attachData方法替代路径传参,避免路径依赖:
public function build() { $this->from(config('mail.from.address'), config('mail.from.name')) ->subject('Your PDF') ->attachData( file_get_contents($this->filePath), 'document.pdf', ['mime' => 'application/pdf'] ); return $this->markdown('emails.pdf-download'); } - 排查IO延迟导致的未完全落盘问题
本地磁盘IO性能高,PDF生成后可以立刻读取到完整内容;生产环境如果使用云盘、分布式存储,IO延迟更高,可能出现文件还没完全写入磁盘就被读取的情况。可以在生成PDF后、发送邮件前增加文件大小校验,或清除文件状态缓存:// 生成PDF后执行 $pdfPath = '你的文件路径'; clearstatcache(true, $pdfPath); // 校验文件大小正常后再触发邮件发送 if (filesize($pdfPath) <= 0) { // 增加重试逻辑,等待文件落盘 usleep(500000); clearstatcache(true, $pdfPath); } - 排查路径解析错误问题
确认$this->filePath为绝对路径,如果使用Laravel Storage存储文件,不要直接传相对路径,需要使用Storage::path($relativePath)方法获取绝对路径再传入attach方法,避免生产环境工作目录与本地不一致导致路径解析错误。
内容的提问来源于stack exchange,提问作者LukeVenter
相关产品推荐
相关产品推荐

