PDF生成ガイド
Report Flow APIを使用したPDF生成の詳細ガイドです。
概要
PDF生成には2つのモードがあります:
| モード | エンドポイント | レスポンス | 用途 |
|---|---|---|---|
| 同期生成 | /file/sync/single | PDFバイナリ | 即座に結果が必要な場合 |
| 非同期生成 | /file/async/single | requestId / url / files 配列 (202 Accepted) | 大量生成やバックグラウンド処理 |
同期生成
基本的な使い方
curl -X POST https://api.re-port-flow.com/v1/file/sync/single \
-H "appkey: your-application-key" \
-H "Content-Type: application/json" \
-d '{
"designId": "550e8400-e29b-41d4-a716-446655440000",
"version": 1,
"content": {
"fileName": "invoice.pdf",
"params": {
"customerName": "山田太郎",
"invoiceNumber": "INV-2024-001",
"items": [
{
"name": "商品A",
"price": 1000,
"quantity": 2
}
]
}
}
}' \
--output invoice.pdf
レスポンスヘッダー
Content-Type: application/pdf
Content-Disposition: attachment; filename="invoice.pdf"
Content-Length: 123456
Request-Id: 550e8400-e29b-41d4-a716-446655440000
File-URL: https://api.re-port-flow.com/v1/file/download/{requestId}
X-File-Mapping: %5B%7B%22fileId%22%3A...%7D%5D
X-File-Mapping は URL エンコード済みの JSON 配列 で、fileId / fileName / share 情報を含みます。クライアント側で decodeURIComponent してから JSON.parse してください。詳細は 単一PDF同期生成エンドポイント を参照。
JavaScript実装例
import axios from 'axios';
import fs from 'fs';
async function generatePDF(params) {
try {
const response = await axios.post(
'https://api.re-port-flow.com/v1/file/sync/single',
{
designId: params.designId,
version: params.version,
content: {
fileName: params.fileName,
params: params.data
}
},
{
headers: {
'appkey': process.env.APP_KEY,
'Content-Type': 'application/json'
},
responseType: 'arraybuffer'
}
);
// ファイルに保存
fs.writeFileSync(params.fileName, response.data);
// レスポンスヘッダから情報を取得
const requestId = response.headers['request-id'];
const fileUrl = response.headers['file-url'];
const fileMapping = JSON.parse(
decodeURIComponent(response.headers['x-file-mapping'] || '%5B%5D'),
);
return { requestId, fileUrl, fileMapping };
} catch (error) {
console.error('PDF生成エラー:', error.response?.data || error.message);
throw error;
}
}
// 使用例
generatePDF({
designId: '550e8400-e29b-41d4-a716-446655440000',
version: 1,
fileName: 'invoice.pdf',
data: {
customerName: '山田太郎',
invoiceNumber: 'INV-2024-001',
items: [
{ name: '商品A', price: 1000, quantity: 2 }
]
}
});
非同期生成
大量のPDFを生成する場合や、タイムアウトを避けたい場合は非同期生成を使用します。
基本的な使い方
# 1. 生成リクエスト
curl -X POST https://api.re-port-flow.com/v1/file/async/single \
-H "appkey: your-application-key" \
-H "Content-Type: application/json" \
-d '{
"designId": "550e8400-e29b-41d4-a716-446655440000",
"version": 1,
"content": {
"fileName": "invoice.pdf",
"params": {...}
}
}'
# レスポンス例 (202 Accepted)
{
"requestId": "550e8400-e29b-41d4-a716-446655440000",
"url": "https://api.re-port-flow.com/v1/file/download/{requestId}",
"files": [
{
"fileName": "invoice.pdf",
"fileId": "7f3d1a2b-4c5e-6f7a-8b9c-0d1e2f3a4b5c",
"share": {
"shareType": "workspace",
"url": "https://app.re-port-flow.com/file/{requestId}/{fileId}",
"passcodeEnabled": false
}
}
]
}
詳細は 単一PDF非同期生成エンドポイント を参照。
JavaScript実装例(ポーリング)
async function generatePDFAsync(params) {
// 1. 非同期生成リクエスト
const response = await axios.post(
'https://api.re-port-flow.com/v1/file/async/single',
{
designId: params.designId,
version: params.version,
content: {
fileName: params.fileName,
params: params.data
}
},
{
headers: {
'appkey': process.env.APP_KEY,
'Content-Type': 'application/json'
}
}
);
const { requestId, url, files } = response.data;
// 2. ZIP ダウンロードURL (url) からまとめて、または個別ファイルを取得
// 個別取得: GET /v1/file/download/{requestId}/{fileId}
const pdfResponse = await axios.get(url, {
headers: { 'appkey': process.env.APP_KEY },
responseType: 'arraybuffer',
});
return {
data: pdfResponse.data,
requestId,
url,
files,
};
}
複数PDF生成(ZIP)
複数のPDFを一度に生成してZIPで取得できます。
同期生成
async function generateMultiplePDFs(designId, contents) {
const response = await axios.post(
'https://api.re-port-flow.com/v1/file/sync/multiple',
{
designId,
version: 1,
contents // ContentDto の配列
},
{
headers: {
'appkey': process.env.APP_KEY
},
responseType: 'arraybuffer'
}
);
// X-File-Mapping ヘッダーからファイルマッピングを取得
const fileMapping = JSON.parse(response.headers['x-file-mapping']);
console.log('生成されたファイル:', fileMapping);
return response.data; // ZIP binary
}
// 使用例
const contents = [
{
fileName: 'invoice_001.pdf',
params: { customerName: '山田太郎', invoiceNumber: 'INV-001' }
},
{
fileName: 'invoice_002.pdf',
params: { customerName: '佐藤花子', invoiceNumber: 'INV-002' }
}
];
const zipData = await generateMultiplePDFs('550e8400-...', contents);
fs.writeFileSync('invoices.zip', zipData);
パラメータの構造
デザインパラメータの取得
生成前に、デザインで使用可能なパラメータ構造を確認できます:
curl -X GET https://api.re-port-flow.com/v1/file/design/parameter/{designId}?version=1 \
-H "appkey: your-application-key"
レスポンス例:
{
"customerName": "string",
"invoiceNumber": "string",
"amount": "number",
"items": [
{
"name": "string",
"price": "number",
"quantity": "number"
}
],
"issueDate": "date"
}
パラメータ型の対応
| 型 | 説明 | 例 |
|---|---|---|
string | 文字列 | "山田太郎" |
number | 数値 | 1000 |
date | 日付(ISO 8601) | "2024-02-12" |
object | ネストしたオブ ジェクト | { "name": "値" } |
array | 配列 | [{ "item": 1 }] |
エラーハンドリング
一般的なエラー
400 Bad Request - バリデーションエラー
{
"statusCode": 400,
"message": [
"designId must be a UUID",
"ファイル名に使用できない文字が含まれています(/ \\ : * ? \" < > | および制御文字は使用不可)"
],
"error": "Bad Request"
}
対処法:
- リクエストボディを確認
- ファイル名の形式を確認(
/ \ : * ? " < > |および制御文字は使用不可)
500 Internal Server Error
{
"statusCode": 500,
"message": "Internal server error",
"error": "Internal Server Error"
}
対処法:
- 一時的なサーバーエラーの可能性
- リトライロジックを実装
- 継続する場合はサポートに連絡
リトライ戦略
async function generatePDFWithRetry(params, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await generatePDF(params);
} catch (error) {
if (error.response?.status === 500 && i < maxRetries - 1) {
// 指数バックオフでリトライ
await new Promise(resolve => setTimeout(resolve, 1000 * Math.pow(2, i)));
continue;
}
throw error;
}
}
}
ベストプラクティス
1. タイムアウト設定
同期生成は120秒でタイムアウトします。大きなPDFの場合は非同期生成を使用してください。
// axios でタイムアウト設定
const response = await axios.post(url, data, {
timeout: 120000 // 120秒
});
2. ファイ ル名のサニタイゼーション
function sanitizeFileName(fileName) {
// / \ : * ? " < > | および制御文字を除去
return fileName.replace(/[\/\\:*?"<>|\x00-\x1F]/g, '_');
}
3. パラメータの検証
function validateParams(params, schema) {
// デザインパラメータスキーマと照合
for (const [key, type] of Object.entries(schema)) {
if (!(key in params)) {
throw new Error(`必須パラメータ ${key} が不足しています`);
}
// 型チェック等
}
}
次のステップ
- 非同期ワークフローガイド
- エラーハンドリング
- MCP Server — Claude / Cursor / VS Code から PDF 生成
- n8n Integration — ノーコードワークフロー連携