跳轉到

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)

return PdfResponse::inline(
    pdf: $pdf,
    filename: "report.pdf", // 供「另存新檔」使用
);

此回應設定 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');
});

參見