jsPDFを使ってPDFを生成したところ、ファイル自体は問題なく作成されるのに、日本語だけが文字化けしてしまう。
このようなトラブルに遭遇すると、多くの人は最初にコードを疑います。
「日本語フォントの登録方法が間違っているのではないか」
「addFontの指定が違うのではないか」
「文字コードの問題ではないか」
「メールへ添付したときにPDFが壊れているのではないか」
こうした可能性を一つずつ調べていくことになります。
実際、私たちが開発した「AI・DX業務改善 自動診断」でも、PDFファイル自体は生成できるものの、日本語が正常に表示されない問題が発生しました。
ところが最終的に判明した原因は、jsPDFの処理そのものではありませんでした。サーバー側で読み込んでいた日本語フォントファイルそのものが不完全だったのです。
問題が発生していたipaexg.ttfは約2.6MB。一方、正常な公式IPAex Gothic Ver.004.01は約6.1MBでした。つまり、ファイル名は正しく、GitHub上にもファイルは存在していたものの、その「中身」が正常ではありませんでした。
今回の教訓
コードが正しいように見えるのに直らない場合は、そのコードが読み込んでいる「実物」も確認する。
これはフォントだけの話ではありません。画像、証明書、秘密鍵、添付ファイルなど、アプリが読み込むバイナリファイルでも同じことが起こります。
この記事では、jsPDFで日本語PDFが文字化けした実例をもとに、原因を効率よく切り分けるための8つの確認手順を、非エンジニアの経営者やWeb担当者にも分かるように解説します。
jsPDFで日本語PDFが文字化けするのはなぜ?
最初に理解しておきたいのは、「PDFを生成できること」と「日本語を正常に表示できること」は別の問題だということです。
PDFが生成できることと日本語が表示できることは別
jsPDFを利用すると、JavaScriptからPDFを生成できます。英数字だけのPDFであれば、比較的簡単に作成できます。しかし日本語を扱う場合は、日本語の文字を表示できるフォントをPDF側で利用できるようにする必要があります。
そのため、PDFファイルは生成された、ダウンロードもできた、ファイルサイズも0ではない、という状態でも、日本語フォントが正しく設定されていなければ文字化けする可能性があります。
つまり、「PDFが作れたからPDF生成処理は正常」とは判断できません。PDFという「容器」は作れていても、その中に日本語を正しく描画するためのフォントが準備できていない可能性があります。
日本語では対応フォントをPDFへ組み込む必要がある
jsPDFで日本語を扱う場合、一般的には日本語に対応したTTF形式などのフォントを読み込み、jsPDFから利用できる状態にします。今回利用していたのはIPAexGothicでした。
手順としては、①日本語フォントファイルを読み込む、②jsPDF内で利用できるように登録する、③登録したフォントを選択する、④その状態で日本語をPDFへ出力する、という流れになります。
今回の正常化後の登録例では、次のようにフォントファイル名とフォントFamily名を分けて管理していました。
const FONT_FILE = 'ipaexg.ttf';
const FONT_FAMILY = 'IPAexGothic';
doc.addFileToVFS(FONT_FILE, fontBase64);
doc.addFont(FONT_FILE, FONT_FAMILY, 'normal', 'Identity-H');
doc.setFont(FONT_FAMILY, 'normal');ここで重要なのは、単にコードをコピーすることではありません。addFileToVFS、addFont、setFontで使う名前の役割を理解し、一貫させることが重要です。
コードが正しくても文字化けすることがある
今回、特に難しかったのがここです。コード側を確認していくと、フォントファイルを読み込んでいる、Base64化している、addFileToVFSしている、addFontしている、setFontしている、という処理自体は存在していました。
すると、どうしても「コードのどこかが微妙に間違っているのではないか」と考えてしまいます。しかし実際には、そのコードが読み込んでいたフォントファイル自体が不完全でした。
コードが正常でも、入力される実物が壊れていれば、正常な結果は得られません。
実際に起きた症状|PDFは生成できるのに日本語だけ文字化け
今回のシステムでは、診断結果をPDFとして生成し、そのPDFを利用者へ渡す機能を実装していました。症状は非常に分かりやすいものでした。
PDFファイルそのものは生成される。しかし、日本語部分が文字化けする。
この状態を見ると、最初にメール添付を疑いたくなります。特に「メールで届いたPDFを開いたら文字化けしている」という場合、Nodemailer、SMTP、メールサーバー、添付処理、受信側メールサービス、PDFビューアなどに原因があるのではないかと考えがちです。
最重要の切り分け
「メールで壊れた」と決めつけず、生成直後のPDFを直接確認する。
メールへ添付する前のPDFがすでに文字化けしていれば、メール送信経路をいくら調査しても解決しません。問題はもっと前の段階にあります。
逆に、生成直後のPDFは正常なのに、メールで受け取ったファイルだけがおかしいのであれば、その段階で初めてメール添付処理を疑えばよいのです。
原因調査では、「怪しそうな場所」ではなく、「問題が最初に発生している場所」を探すことが重要です。

原因は約2.6MBの不完全なIPAexGothicフォントだった
今回の決定的な原因は、サーバー側へ配置されていた日本語フォントファイルでした。
問題のipaexg.ttfは約2.6MBだった
システム上にはipaexg.ttfというファイルが存在していました。名前だけを見ると、必要な日本語フォントがきちんと配置されているように見えます。ところが調査すると、そのファイルサイズは約2.6MBでした。今回の実践手順では、このファイルを不完全なファイルとして切り分けました。
正常な公式IPAex Gothic Ver.004.01は約6.1MBだった
一方、正常な公式IPAex Gothic Ver.004.01は約6.1MBでした。つまり、同じipaexg.ttfというファイル名でも、問題が起きていたものは約2.6MB、正常なものは約6.1MBと、実体が大きく異なっていました。
この違いが分かれば、「コードが何度直しても改善しない」という状態にも説明がつきます。不完全なフォントを何度正しくaddFontしても、元データが正常でなければ日本語は正しく表示されません。
ファイルが「存在する」ことと「正常である」ことは違う
今回最も大きな学びはここです。開発では「ファイルがあるか」を確認することはよくあります。しかし本当に確認すべきなのは、「そのファイルの実体が正しいか」です。
| 確認項目 | 問題発生時 | 正常化後 |
|---|---|---|
| ipaexg.ttf | 約2.6MB | 約6.1MB |
| フォント実体 | 不完全 | 正常な公式フォント |
| jsPDF登録 | 名前の扱いが曖昧 | ファイル名とFamily名を明示 |
| 検証 | 見た目中心 | テキスト抽出でも確認 |
確認するときは、少なくとも次の3点を見ます。
ファイルサイズ:極端に小さくないか、想定した公式ファイルと同程度か確認する。
ハッシュ:ファイルの中身から計算される「指紋」のような値。同じ名前でも中身が違えば通常ハッシュも変わる。
実体:GitHub上で存在しているだけで安心せず、本当に正しいバイナリが保存されているか確認する。
jsPDFの日本語文字化けを調べる8つの手順
ここからは、同じトラブルが起きた場合に、どの順番で確認すればよいかを整理します。重要なのは、手当たり次第に修正しないことです。上流から一段ずつ原因を切り分けます。

1.メールを疑う前に生成直後のPDFを確認する
最初に確認するのは、メールではありません。PDF生成直後のファイルです。
サーバーやアプリから生成したPDFを、メールへ添付する前に直接確認します。ここで日本語がすでに文字化けしているなら、SMTP、Nodemailer、メールサーバー、受信メールアプリを調査する必要はありません。原因はPDF生成側にあります。
メール送信も、画面→API→メール生成関数→SMTP接続→外部メールボックスというように段階を分けて確認します。PDFも同様に、どこまで正常だったのかを一段ずつ確認することで調査範囲を小さくできます。
2.実際にPDFを生成しているコードを特定する
次に確認するのが、「どのコードが本当にPDFを生成しているのか」です。
server/pdfGenerator.tsなど、実際に本番で利用されているPDF生成コードを確認し、src側の別実装などと混同しないようにします。
AIへ「PDFの文字化けを直してください」と依頼すると、AIが見つけた似た処理を修正してしまうことがあります。しかし、そのコードが本番で呼ばれていなければ、何度修正しても本番の結果は変わりません。
確認するべきなのは、どのAPIから呼ばれているか、本番で使っている生成関数は何か、同じ名前の別実装がないか、修正したファイルが実際の実行経路にあるか、です。
「正しいコードを修正した」ではなく、「実際に使われているコードを修正した」ことを確認してください。
3.フォントファイルのサイズ・ハッシュ・実体を確認する
ここが今回の原因となった最重要ポイントです。コードに問題が見つからない場合、次に確認するのは、フォントファイルそのものです。
特に確認したいのは、ファイルサイズ、ハッシュ、GitHub上のファイル実体、配置されている場所、本番環境で読み込んでいるファイルです。
今回のケースでは、ipaexg.ttfというファイル名自体は合っていました。だからこそ発見が遅れました。ファイル名だけ見れば「ある」。コードからも「読んでいる」。しかし実体は不完全だった。このような問題は、コードレビューだけでは見落としやすい部分です。
4.正常な公式フォントへ差し替える
不完全なフォントであることが分かったら、正しいフォントへ差し替えます。
ライセンスと配布元を確認し、正しいTTFを配置します。インターネット上で見つけた「同名ファイル」を適当に置き換えるのではなく、配布元、バージョン、ライセンス、ファイルサイズまで確認したうえで利用してください。
差し替え後には、「ファイルを置いたから終わり」ではなく、次のjsPDF登録設定まで確認します。
5.addFileToVFS・addFont・setFontの名前をそろえる
jsPDFで日本語フォントを利用する場合、名前の不一致にも注意が必要です。
非エンジニア向けに簡単に説明すると、addFileToVFSはjsPDFから参照できる場所へフォントファイルを登録する処理、addFontは登録したファイルを「この名前のフォントとして使います」とjsPDFへ教える処理、setFontは実際に文字を書くときにどのフォントを使うか選択する処理です。
重要なのは、addFontで登録したFamily名と、setFontで利用する名前をそろえることです。たとえばIPAexGothicというFamily名で登録したのに、別の名前をsetFontへ渡せば、想定した日本語フォントが選択されない可能性があります。
const FONT_FILE = 'ipaexg.ttf';
const FONT_FAMILY = 'IPAexGothic';
doc.addFileToVFS(FONT_FILE, fontBase64);
doc.addFont(FONT_FILE, FONT_FAMILY, 'normal', 'Identity-H');
doc.setFont(FONT_FAMILY, 'normal');6.ビルド成果物へフォントが含まれているか確認する
ソースコード上でフォントが存在していても、本番環境へ入っているとは限りません。Cloud Runなどでアプリを動かしている場合、Dockerfile、package build、コピー対象ディレクトリ、ビルド成果物を確認します。
たとえばDockerfile/package buildでserver/fontsがコピーされることを確認します。開発環境にはフォントが存在しても、Dockerイメージへコピーされていなければ、ローカルと本番で結果が変わります。
「GitHubにある」だけでは本番に存在する証拠にはなりません。
7.PDFのテキストを抽出して日本語を確認する
PDFが見た目上正常になったら、さらに一段確認します。PDF内のテキストを抽出して、日本語が正常に取得できるか確認します。
PDFは「画面では文字に見えている」状態と、「内部に正しい文字情報が入っている」状態が必ずしも同じとは限りません。
将来的にPDF検索、コピー&ペースト、PDF解析、AIによるPDF読み取り、文書管理などへ利用する可能性があるなら、テキストとして正常に扱えることも重要です。
8.生成PDFが正常になってからメール添付を確認する
最後にメール添付を確認します。順番を逆にしないことが重要です。
生成直後のPDFが正常になったあとで、診断結果メール、添付ファイル、実際の受信メール、受信後のPDFを確認します。
PDF生成のテストと、メール送信のテストは別々に行うことで、「PDFが悪いのか」「メールが悪いのか」を混同せずに済みます。
jsPDFの日本語文字化け調査チェックリスト
調査の抜け漏れを防ぐために、確認済みの項目をチェックしながら進めてください。
| 確認フェーズ | チェック項目 |
|---|---|
| 切り分け | ☐ メール添付前の生成直後PDFを確認した ☐ 生成直後PDFでも日本語が文字化けしているか確認した |
| 生成コード | ☐ 本番で実際に利用されているPDF生成コードを特定した ☐ 別のPDF生成実装を修正していないか確認した |
| フォント実体 | ☐ フォントファイルのサイズを確認した ☐ フォントファイルのハッシュを確認した ☐ GitHub上のフォント実体を確認した ☐ Git LFSやアップロード時の破損を疑った ☐ 正しい配布元のフォントへ差し替えた |
| jsPDF登録 | ☐ addFileToVFSのファイル名を確認した ☐ addFontのFamily名を確認した ☐ setFontで同じFamily名を使用している |
| ビルド | ☐ Dockerやビルド成果物へTTFが含まれている ☐ 本番環境でも同じフォントを読み込んでいる |
| PDF検証 | ☐ PDFの見た目で日本語を確認した ☐ PDFから日本語テキストを抽出できることを確認した |
| メール・再確認 | ☐ 最後にメール添付PDFを確認した ☐ 再デプロイ後も正常であることを確認した |
AIに修正を任せると「コード側」ばかり見てしまう理由
今回の問題は、AIを使った開発だからこそ得られた重要な教訓でもあります。AI StudioやClaude Codeなどを利用すると、非エンジニアでも大量のコードを短時間で作成・修正できます。これは非常に大きなメリットです。
一方で、AIへ「この文字化けを直してください」と依頼すると、どうしてもコード側を重点的に分析することになります。
AIはコードの矛盾を探すのは得意
変数名の不一致、関数の呼び出し漏れ、import漏れ、setFontの指定ミス、ファイルパスの間違いなどは、AIが比較的見つけやすい領域です。コード自体がテキストなので、AIがその内容を読んで比較できるからです。
しかし壊れたバイナリはコードを読んでも分からない
一方、ipaexg.ttfという名前のファイルがあったとしても、AIがコードを読むだけでは、そのファイルが本当に正常なフォントなのか判断できない場合があります。これが「バイナリの盲点」です。
バイナリとは、簡単に言えば、フォントや画像など、プログラムが読み込む実ファイルだと考えてください。フォント、画像、PDF、証明書、秘密鍵、添付ファイル、学習済みモデルなどが該当します。
コードに「このファイルを読み込む」と正しく書いてあっても、実ファイルが壊れていれば正常には動きません。
「修正完了」ではなく実成果物を確認する
AI Studioで「修正完了しました」と表示されても、それは本番で直ったことを意味しません。同じように「フォント登録コードを修正しました」という報告も、実際に生成されたPDFが正常になった証拠ではありません。
| 段階 | 確認するもの | 完了の証拠 |
|---|---|---|
| 1 AI Studio | コード・lint・build | 実ファイルが存在し、ローカルビルド成功 |
| 2 GitHub | mainの差分 | コミットSHAと変更ファイル |
| 3 Cloud Build | ビルド | 成功ログ |
| 4 Cloud Run | リビジョン | 新Revisionが100% traffic |
| 5 本番 | 実機 | 実際のユーザー操作が成功 |
最終的には人間が成果物を見る必要があります。
コードが正しいのに直らないときは「読み込んでいる実物」を疑う
今回の記事で最も伝えたいのは、jsPDFの細かな書き方だけではありません。コードが正しいように見えるのに直らない場合は、そのコードが読み込んでいる実物を疑う。これが非常に重要です。
ソースコードだけを見るデバッグには限界がある
一般的な不具合調査では、「どのコードが間違っているか」を探します。しかしアプリはコードだけで動いているわけではありません。コードから、フォントを読む、画像を読む、証明書を読む、Secretを読む、データベースへ接続するなど、さまざまな外部要素を利用しています。
そのため、コードに間違いがない=システム全体が正しいとは限りません。
ファイル名が正しくても中身が正しいとは限らない
今回のipaexg.ttfは、その典型です。ファイル名は合っていました。コードもその名前を参照していました。しかしサイズを確認すると、正常なものとは大きく違っていました。
このようなケースでは、「あるか、ないか」ではなく、「正しい実体か」まで確認する必要があります。
サイズ・ハッシュ・実体を見る習慣をつける
今後AIでアプリを開発するときは、不具合調査に次の観点を追加すると整理しやすくなります。
| 観点 | 確認する内容 |
|---|---|
| コード | 処理のロジックが正しいか |
| 設定 | 環境変数やパス、登録名が正しいか |
| 実物 | 読み込んでいるファイルやデータは正しいか |
| ビルド | 本番成果物へ入っているか |
| 本番 | 実際の利用環境で動いているか |
PDFが直った後も触ってはいけない領域を決める
文字化けが解消したあとにも注意が必要です。一度正常化したPDF機能を、別の修正によって再び壊してしまう可能性があるからです。
正常化した機能を別修正から分離する
たとえば、認証を変更する、Firestoreを修正する、UIを変更する、メール送信機能を追加するといった作業では、PDF関連ファイルまで一緒に変更しないようにします。
AIへ修正を依頼するときも、「PDF生成機能は正常化済みなので変更しない」と明示したほうが安全です。
再デプロイ後に回帰テストする
回帰テストとは、以前正常だった機能が、別の修正後も正常か確認するテストです。PDF文字化けが一度直っても、ビルド設定変更、Dockerfile変更、ディレクトリ移動、フォント更新などによって再発する可能性があります。
回帰テストでは、日本語PDFのテスト生成、実診断PDFの生成、PDFファイルサイズ、日本語文字化けの有無、メール添付の5点を確認します。
よくある質問
jsPDFは日本語をそのまま表示できますか?
日本語を正常に表示するには、日本語に対応したフォントを利用できる状態にする必要があります。PDF自体が生成できても、日本語用フォントが正しく登録・選択されていなければ文字化けする可能性があります。まずは利用しているフォント、jsPDFへの登録、実際にsetFontされているフォントを確認してください。
addFontを設定しているのに文字化けするのはなぜですか?
addFontだけを確認するのではなく、元のフォントファイルが正常か、addFileToVFSへ正しいファイルを登録しているか、addFontのFamily名が正しいか、setFontでそのFamily名を利用しているか、本番ビルドへフォントが含まれているかを順番に確認してください。今回の実例では、コードよりも前に、元のフォントファイル自体が不完全でした。
フォントファイルがGitHubにあれば正常ですか?
いいえ。GitHub上にファイルが存在することと、そのファイルの中身が正常であることは別です。今回もipaexg.ttfというファイル自体は存在していましたが、約2.6MBの不完全なファイルでした。ファイルサイズ、ハッシュ、実体まで確認することをおすすめします。
メール添付するとPDFが文字化けする場合はどこを確認しますか?
最初に、メールへ添付する前の生成直後PDFを確認してください。そのPDFがすでに文字化けしている場合、原因はメール経路ではありません。生成直後のPDFが正常であることを確認してから、NodemailerやSMTP、添付処理などを調査します。
AIにコードを直してもらっても改善しない場合はどうすればよいですか?
コード以外を確認してください。特に、フォント、画像、証明書、環境変数、Secret、ビルド成果物など、コードが外部から読み込んでいる実物を確認します。また、AIが「修正完了」と回答しても、GitHub・Cloud Build・Cloud Run・本番まで実際に反映されたかは別途確認してください。
まとめ|コードが正しいなら次はフォントの「実物」を確認する
jsPDFでPDFは生成できるのに日本語だけが文字化けする場合、コードだけを何度も修正する前に、原因を順番に切り分けることが重要です。
今回の実例では、最終的な原因はipaexg.ttfでした。問題が起きていたファイルは約2.6MBで、正常な公式IPAex Gothic Ver.004.01は約6.1MBでした。
①メールへ添付する前の生成直後PDFを確認する、②実際に本番で使われているPDF生成コードを特定する、③フォントのサイズ・ハッシュ・実体を確認する、④正常な公式フォントへ差し替える、⑤addFileToVFS・addFont・setFontの名前を一貫させる、⑥ビルド成果物へフォントが含まれているか確認する、⑦PDFから日本語テキストを抽出して確認する、⑧最後にメール添付経路を確認する。この順番が調査の近道です。
そして、今回のトラブルから得られた最も大きな教訓は、コードが正しいのに動かないなら、コードが読み込んでいる実物も確認するということです。
AIを使った開発では、コード修正そのものは非常に速くなりました。しかしAIがコードを何度直しても問題が解決しないときには、人間側が調査対象を広げる必要があります。
フォント、画像、証明書、設定値、ビルド成果物。システムはコードだけでは動いていません。
「修正した」という報告ではなく、実際に生成された成果物が正常になったところまで確認することが、本番システムを安定して運用するうえで重要です。
AIを使った業務改善について相談する
AIを使えば、非エンジニアでも業務アプリを作れる時代になりました。一方で、今回のPDF文字化けのように、コードを何度修正しても原因へたどり着けないことがあります。「AIに何を確認させればよいか分からない」「GitHub、Cloud Build、Cloud Runのどこで問題が起きているのか判断できない」「自社の業務をAIでどこまで仕組み化できるか整理したい」という場合は、現在の業務や作りたい仕組みを整理したうえで、専門家へ相談する方法もあります。
AIを使った業務改善について相談する
