HTTP 回應¶
PdfResponse 封裝 PDF bytes 為 Laravel HTTP 回應物件,並自動注入 OWASP 建議的安全標頭,防止 XSS、MIME sniffing 與快取敏感文件等風險。
PHP Compatibility
This example uses PHP 8.5 syntax. If your environment runs PHP 8.1 or 7.4, use NextPDF Backport for a backward-compatible build.
下載回應(Attachment)¶
<?php
declare(strict_types=1);
namespace App\Http\Controllers;
use NextPDF\Laravel\Facades\Pdf;
use NextPDF\Laravel\Http\PdfResponse;
final class InvoiceController extends Controller
{
public function download(int $id): PdfResponse
{
$pdf = Pdf::create()->addPage()->output();
return PdfResponse::download(
pdf: $pdf,
filename: "invoice-{$id}.pdf",
);
}
}
此回應會設定 Content-Disposition: attachment; filename="invoice-{id}.pdf",觸發瀏覽器下載對話框。
內嵌預覽(Inline)¶
此回應設定 Content-Disposition: inline,現代瀏覽器會在頁面內嵌顯示 PDF 閱讀器。
OWASP 安全標頭¶
PdfResponse 預設注入以下標頭,遵循 OWASP Secure Headers Project 建議:
| 標頭 | 預設值 | 說明 |
|---|---|---|
Content-Type | application/pdf | 精確 MIME 型別 |
X-Content-Type-Options | nosniff | 防止 MIME sniffing |
Content-Security-Policy | default-src 'none' | 阻擋所有外部資源 |
Cache-Control | no-store, max-age=0 | 防止敏感文件被快取 |
X-Frame-Options | DENY | 防止 Clickjacking |
Referrer-Policy | no-referrer | 不洩漏來源 URL |
Pragma | no-cache | HTTP/1.0 快取控制 |
自訂標頭¶
use NextPDF\Laravel\Http\PdfResponse;
use NextPDF\Laravel\Http\PdfResponseConfig;
return PdfResponse::download(
pdf: $pdf,
filename: 'report.pdf',
config: PdfResponseConfig::create(
cacheMaxAge: 300, // 允許快取 5 分鐘(公開報告)
xFrameOptions: 'SAMEORIGIN', // 允許同源 iframe 嵌入
additionalHeaders: [
'X-Report-ID' => $reportId,
'X-Generated-At' => now()->toIso8601String(),
],
),
);
串流大型 PDF¶
對於超過 50MB 的大型 PDF,建議使用串流回應避免將整份文件載入記憶體:
use NextPDF\Laravel\Http\PdfStreamResponse;
return PdfStreamResponse::download(
generator: function () use ($document): \Generator {
yield from $document->stream(); // 分塊輸出
},
filename: 'large-report.pdf',
estimatedSize: 104857600, // 可選:提供 Content-Length 標頭(bytes)
);
條件性下載(ETag + 304)¶
對於可快取的公開報告,可啟用 ETag 支援:
return PdfResponse::download(
pdf: $pdf,
filename: 'annual-report-2026.pdf',
config: PdfResponseConfig::create(
etagSource: hash('sha256', $pdf), // 從 PDF bytes 計算 ETag
cacheMaxAge: 86400, // 公開快取 24 小時
cacheVisibility: 'public',
),
);
在測試中斷言回應¶
it('returns a pdf download response', function () {
$response = $this->get('/invoices/1/download');
$response->assertStatus(200);
$response->assertHeader('Content-Type', 'application/pdf');
$response->assertHeader('Content-Disposition', 'attachment; filename="invoice-1.pdf"');
$response->assertHeader('X-Content-Type-Options', 'nosniff');
$response->assertHeader('Cache-Control', 'no-store, max-age=0');
});
參見¶
- Laravel 套件總覽 — 套件功能概覽
- Facade — Pdf Facade 生成 PDF bytes
- Queue Job — 非同步生成後透過通知發送下載連結