pdfjs-dist をサーバーサイドで動かして PDF を画像化し、PDF のサムネイルを作る方法
こんにちは。OSSのPDFライブラリ - pdfme を開発している Kyohei です。
サーバーサイドでPDFを画像に変換したいケースは地味に多いものの、ブラウザ向けの事例はあってもNode.js環境向けの例は少ない印象があります。
そこでpdfjs-distを活用し、Node.js上でPDFを画像変換を簡単にできるように秘伝のタレをライブラリ化しました。
本記事では、その中の pdf2img 関数を使ってPDFのサムネイルを生成する方法を紹介します。
1. 何を作ったか
@pdfme/converter
の pdf2img
関数
pdf2img(pdf: ArrayBuffer, options?: Pdf2ImgOptions): Promise<ArrayBuffer[]>
-
npm install @pdfme/converter
で導入可能 - ドキュメント を見れば基本的な使い方がわかります
この関数は既に https://app.pdfme.com/ のテンプレート機能で運用中です。
他にも https://pdfme.com のテンプレート一覧ページ( https://pdfme.com/templates )で PDF のサムネイルを生成するために利用されています。
2. サンプルコード
import fs from 'fs';
import path from 'path';
import { pdf2img } from '@pdfme/converter';
async function generateThumbnail(pdfPath: string, thumbnailPath: string): Promise<void> {
try {
const pdf = fs.readFileSync(pdfPath);
const pdfArrayBuffer = pdf.buffer.slice(pdf.byteOffset, pdf.byteOffset + pdf.byteLength);
const images = await pdf2img(pdfArrayBuffer, {
imageType: 'png',
range: { end: 1 },
});
const thumbnail = images[0];
fs.writeFileSync(thumbnailPath, Buffer.from(thumbnail));
console.log(`Thumbnail saved to ${thumbnailPath}`);
} catch (err) {
console.error(`Failed to generate thumbnail from ${pdfPath} to ${thumbnailPath}`, err);
}
}
- PDF バイナリを ArrayBuffer 化→
pdf2img
関数に投げる→返ってきた画像配列の先頭をthumbnailPath
に保存する流れです。 -
range
オプションでページ範囲を指定。ここでは先頭ページのみサムネイルを作るようにしています。
3. なぜ作ったか
多くのブログ記事は PDFjs を ブラウザ上 で動かす方法ばかり。ですが私の目的は サーバーサイド で PDF を画像に変換することでした。
また、PDF 関連の別プロジェクトでも毎回似たコードを書いていたため、「すぐに使えるライブラリ」にまとめたかったのです。
いくつかのプロジェクトでこの関数を書いて得られた知見は下記です。
-
pdfjs-dist は v3 系でないと Node.js で動かない
→ FAQ にもある通り、Node.js はレガシービルドを使う必要がある - node canvas は v2 系でないと動かない
- PDF 内のフォント は埋め込まれている必要がある
これらをもとに、同じ様なことでハマる人が少なくなれば...と思い、このライブラリを作りました。
4. これから作りたい機能
- md2pdf: Markdown から PDF を生成する機能 (PoC は完成済み)
- pdf2md: PDF からテキストを抽出して Markdown 化 (おおよその実装方針は見えている)
- manipulator パッケージ: PDF のページの削除・追加などの編集機能も拡張予定
5. サーバーレス使用時の注意
-
node-canvas
を入れるため Lambda 等のファンクション容量制限に注意が必要です - Vercel の場合は「サムネイル生成専用ファンクション」に切り分けることで対応可能です
6. まとめ
サーバーサイドで動く PDF 画像変換は想像以上に面倒ですが、@pdfme/converter
を使えばセットアップがシンプルにまとまります。ブラウザ・サーバー共通で使えるのが強みなので、「まずは PDF をサムネイルにしたい」というニーズがあるなら試してみてください。
PDF 周りで困ったときはいつでも声をかけてください。
もろもろの進捗は X でも発信するので、気になった方はフォローお待ちしています。
Discussion