🚀 新規事業

pdf-export-pattern

最終更新 2026年05月09日 / 40_新規事業/SCALE_Build/カタログ/機能集/pdf-export-pattern.md

PDFエクスポートパターン

用途

HTMLレポートをPDFに変換してダウンロード/メール送信するパターン。

特徴

  • HTML→PDF変換
  • スタイル保持
  • メール送信
  • ダウンロード

コード(コピペ用)

// クライアントサイドPDF生成(@react-pdf/renderer 不要・印刷API利用)
export async function exportToPDF(elementId: string, filename = 'report.pdf') {
  const el = document.getElementById(elementId);
  if (!el) throw new Error(`Element not found: #${elementId}`);

  // 印刷用 iframe を生成
  const iframe = document.createElement('iframe');
  iframe.style.cssText = 'position:fixed;right:0;bottom:0;width:0;height:0;border:0';
  document.body.appendChild(iframe);

  const doc = iframe.contentWindow!.document;
  doc.write(`<!DOCTYPE html><html><head><title>${filename}</title>`);
  // 親ページのスタイルを継承
  document.querySelectorAll('link[rel="stylesheet"], style').forEach((s) => {
    doc.head.appendChild(s.cloneNode(true));
  });
  doc.write(`</head><body>${el.outerHTML}</body></html>`);
  doc.close();

  iframe.contentWindow!.focus();
  iframe.contentWindow!.print();

  setTimeout(() => document.body.removeChild(iframe), 1000);
}

// サーバサイド PDF(Cloudflare Workers + Browser Rendering)
export async function generatePDFServer(env: { BROWSER: any }, html: string): Promise<ArrayBuffer> {
  const browser = await env.BROWSER.launch();
  const page = await browser.newPage();
  await page.setContent(html);
  const pdf = await page.pdf({ format: 'A4', printBackground: true });
  await browser.close();
  return pdf;
}

// 使い方:
// <button onClick={() => exportToPDF('report-area', '月次レポート.pdf')}>PDF出力</button>

使い方

対象プロジェクトに該当ファイルをコピーして、props を流し込むだけ。

注意事項

  • 依存パッケージを忘れず追加