如何将Browsershot流式PDF附加到Laravel邮件并设置正确MIME类型?
解决Laravel流式PDF附件MIME类型不正确的问题
针对你遇到的Browsershot流式生成PDF后,邮件附件MIME类型始终为application/octet-stream的问题,提供几个无需持久化磁盘的可行方案:
方案1:手动补全PDF文件头标识
Browsershot返回的流式PDF内容可能缺失标准PDF文件头(%PDF-开头),导致系统无法识别为PDF类型。可以手动检查并添加:
$pdfContent = Browsershot::url('https://example.com')->pdf(); // 确保内容以标准PDF头开头 if (!str_starts_with($pdfContent, '%PDF-')) { $pdfContent = '%PDF-1.7' . $pdfContent; } // 附加到邮件并指定MIME $message->attachData( $pdfContent, 'document.pdf', ['mime' => 'application/pdf'] );
方案2:使用临时内存存储获取正确MIME
利用系统临时目录存储PDF(执行后立即删除,不占用持久磁盘空间),通过Laravel Storage获取正确的MIME类型:
// 构建临时磁盘(指向系统临时目录) $tempStorage = Storage::build([ 'driver' => 'local', 'root' => sys_get_temp_dir(), ]); $tempFilename = 'temp-pdf-' . uniqid() . '.pdf'; // 生成PDF到临时文件 Browsershot::url('https://example.com')->savePdf($tempStorage->path($tempFilename)); // 获取文件内容和正确MIME $pdfContent = $tempStorage->get($tempFilename); $correctMime = $tempStorage->mimeType($tempFilename); // 附加到邮件 $message->attachData($pdfContent, 'document.pdf', ['mime' => $correctMime]); // 清理临时文件 $tempStorage->delete($tempFilename);
方案3:强制设置邮件附件头信息
部分情况下attachData的mime参数会被邮件底层的自动识别逻辑覆盖,手动指定完整的HTTP头信息强制修正:
$pdfContent = Browsershot::url('https://example.com')->pdf(); $message->attachData( $pdfContent, 'document.pdf', [ 'mime' => 'application/pdf', 'headers' => [ 'Content-Type' => 'application/pdf; charset=utf-8', 'Content-Disposition' => 'attachment; filename="document.pdf"', ], ] );
问题根源
Browsershot的pdf()方法直接返回二进制流,但该流没有经过文件系统的签名识别环节;而savePdf()写入文件后,系统能通过PDF的文件签名(开头的%PDF-)自动识别正确的MIME类型,所以会出现两种方式结果不同的情况。
内容的提问来源于stack exchange,提问作者Whipenstein
相关产品推荐
相关产品推荐

