Base64 を PDF にデコードする方法
- Base64 または data URI に文字列を貼り付けます。
data:application/pdf;base64,…形式の URI 全体でもかまいません。改行、前後の引用符、URLセーフ Base64(-と_)、=パディングの欠落もそのまま扱えます。ファイルに保存された長い文字列は .txt ファイルを開く を使うか、入力欄にドロップしてください。4 MB を超えるものはテキストエリアに表示せずにデコードします。 - ボタンの下にプレビューが開きます。貼り付けた時点でデコードが始まります。自分で デコード を押したい場合は リアルタイム のチェックを外してください。
- ファイル名 を確認します。初期値は
decodedですが、data URI にname=パラメータがあればその名前を、開いたテキストファイルがあればその名前を使います。invoice.pdf.b64.txtならinvoice.pdfになります。 - ファイルをダウンロード を押します。プレビューの下にあるリンク 新しいタブで開いてください からは、同じ PDF を全画面で表示できます。
ページを開いた時点でサンプルの PDF が読み込まれているので、自分のデータを貼り付ける前に、正しく動いたときの結果を確認できます。
Base64 の PDF はどこから来るのか
JSON には生のバイト列を載せる手段がないため、JSON API でドキュメントを返すサービスは Base64 文字列として送ります。フィールド名は content、document、file、label などが一般的です。
- ラベルや物流の API は、印刷用の配送ラベルを Base64 の PDF で返します。同じリクエストでもフォーマット指定のパラメータ次第で ZPL や PNG が返ることが多く、「PDF」のフィールドが必ずしも PDF とは限りません(後述の表を参照)。
- 電子署名サービスは、署名済みドキュメントと、多くの場合は別の監査証明書を、完了時のレスポンスや Webhook の中で Base64 として返します。
- UBL 形式の XML による電子請求書には、人が読める PDF の写しが
<cbc:EmbeddedDocumentBinaryObject mimeCode="application/pdf" filename="INV-1001.pdf">のような要素に埋め込まれています。タグの間のテキストをコピーしてください。filename属性の値を ファイル名 に入力すれば元の名前になります。 - メールの生ソースでは、PDF の添付は
Content-Transfer-Encoding: base64の MIME パートで、1 行 76 文字で並んでいます。エンコードされたブロックだけを貼り付けるか、メッセージ全体を EML デコーダー で開けば、すべての添付ファイルが一覧表示されます。構造については メールでの Base64 で解説しています。 - データベースの BLOB カラムに保存されたドキュメントは、テキストとしてエクスポートされることがよくあります。PostgreSQL の
encode(data, 'base64')も、MySQL や MariaDB のTO_BASE64()も、76 文字ごとに改行を入れますが、デコーダーはこれを無視します。
エンコードされたフィールドが複数ある JSON レスポンスなら、JSON 内の Base64 をデコード を使うと一度にすべて見つけてデコードできます。逆に PDF ファイルから文字列を作るには PDF を Base64 に変換 を使ってください。
プレビューに表示される情報
| 項目 | 取得元 |
|---|---|
| PDF バージョン | ヘッダー行(例:%PDF-1.7) |
| ページ数 | ファイル内のページオブジェクトから数えた値(下記参照) |
| タイトル | 文書情報のタイトル(プレーンテキストで保存されている場合) |
| 暗号化 | ファイルに暗号化辞書がある場合に表示。開くためのパスワード、または権限の制限のみ |
| SHA-256 | デコード後のバイト列のハッシュ。送信側で sha256sum invoice.pdf の結果と比べれば、ファイルが欠けずに届いたことを証明できます |
プレビュー自体はブラウザの PDF ビューアで、ローカルの blob: URL からデコード済みのバイト列を表示しています。Chrome、Edge、Firefox、デスクトップ版 Safari はページ内に表示します。ブラウザが PDF を開かずにダウンロードする設定になっていると、プレビューは空白のままです(Chrome:設定 → プライバシーとセキュリティ → サイトの設定 → その他のコンテンツの設定 → PDF ドキュメント、Firefox:設定 → 一般 → プログラム → Portable Document Format)。また、多くのモバイルブラウザはページ内で PDF を描画できません。そうした場合でも 新しいタブで開いてください や ファイルをダウンロード は使えますし、プレビュー上の情報欄はどちらの場合も表示されます。
ページ数の数え方
このツールはページ数を数えるために PDF を描画しません。ファイルの先頭 32 MB にあるページオブジェクト(/Type /Page)を数えます。それが見つからなければページツリーの /Count を読み、それも見えなければ 不明 と表示します。ビューアの表示と数が食い違うのは次の 2 つの場合です。
- ページ数が多すぎる。 作成後に編集、注釈、署名が加えられた PDF は、増分保存されていることがよくあります。変更されたページは新しいオブジェクトとして追記され、古い版もファイルに残ります。2 ページのうち 1 ページを書き換えたテストファイルでは、数は 3 になりました。
- 不明。 PDF 1.5 以降では、オブジェクトを圧縮オブジェクトストリームにまとめられます。この場合、展開しない限りページオブジェクトもページツリーも読み取れません。
両者が食い違うときは、ビューアのページ数が正しい値です。
結果が PDF ではない場合
デコードしたバイト列が別の形式だった場合は、項目の上に検出結果を示す注意書き(例:「これは PDF ではなく HTML のようです。」)が表示され、.html としてダウンロード ボタンが付きます。何が起きたかは、Base64 の先頭を見ればたいてい分かります。
| Base64 の先頭 | 中身 |
|---|---|
JVBERi0 | PDF(%PDF-) |
SlZCRVJpMH | 二重にエンコードされた PDF:JVBERi0… をさらに Base64 にしたもの |
H4sI | gzip で圧縮されたデータ |
PCFET0NUWVBF、PCFkb2N0eXBl、PGh0bWw | HTML ページ。たいていはエラーページかログインページ |
eyJ | JSON。多くは {"error":… のようなエラーメッセージ |
XlhB | サーマルプリンター用の ZPL ラベル(^XA) |
iVBORw0KGgo | PNG 画像 |
二重エンコードされた文字列や gzip データの場合は、2 つ目の注意書きに もう一度デコード が表示され、入力が内側のデータに置き換わります。戻る を押すと貼り付けた元の内容に戻ります。破損しているか判別できないファイルの場合は「PDF ではないようです」と表示されて検出された形式が示されますが、拡張子は .pdf のままなので、バイト列をダウンロードして別のリーダーで試すことができます。
デコード前のエラーには、それぞれ別の原因があります。
- 生の JSON に含まれるエスケープ(PHP の
json_encodeが出力するスラッシュの\/や、行間にある文字どおりの\nなど)は自動的に取り除かれます。それ以外の\エスケープで 無効な文字\が出る場合は、Base64 を修復 を使うか、先に JSON をパースしてから値をコピーしてください。 - 無効な文字
%は、文字列が URL エンコードされていることを意味します。+、/、=のエスケープ(%2B、%2F、%3D)は自動で直りますが、それ以外は先に URL デコーダー に通してください。 - PDF として検出されるのに何も表示されない 場合は、たいてい途中で切れています。ヘッダーは残っているので検出には成功しますが、相互参照テーブルがあるファイルの末尾が失われています。その他のよくある原因は Base64 のエラー を参照してください。
コードで Base64 を PDF にデコードする
Python で JSON レスポンスから取り出す例です。
import base64, json
with open("response.json") as f:
b64 = json.load(f)["document"]
if b64.startswith("data:"):
b64 = b64.split(",", 1)[1]
pdf = base64.b64decode(b64)
if not pdf.startswith(b"%PDF-"):
raise ValueError(f"not a PDF, starts with {pdf[:16]!r}")
with open("document.pdf", "wb") as f:
f.write(pdf)
b64decode は標準アルファベット以外の文字を黙って捨てるため、- と _ を含む URLセーフな文字列はエラーにならずに壊れたデータになります。そうした文字列には base64.urlsafe_b64decode を使ってください。Node.js は 1 回の呼び出しで両方のアルファベットを受け付けます。
import { readFile, writeFile } from "node:fs/promises";
const { document } = JSON.parse(await readFile("response.json", "utf8"));
const pdf = Buffer.from(document.replace(/^data:[^,]*,/, ""), "base64");
if (pdf.toString("latin1", 0, 5) !== "%PDF-") throw new Error("not a PDF");
await writeFile("document.pdf", pdf);
シェルでは jq -r が重要です。-r を付けないと値に引用符が残り、base64 -d が「invalid input」で止まります。
jq -r '.document' response.json | base64 -d > document.pdf
キーの document は仮の名前なので、お使いの API のフィールド名に置き換えてください。その他のパターンは Python での Base64、Node.js での Base64、Bash での Base64 にあります。
よくある質問
Base64 文字列を PDF ファイルに変換するには?
上の入力欄に文字列を貼り付け、プレビューを確認して ファイルをダウンロード を押します。JSON からは引用符の間の値だけをコピーしてください。data:application/pdf;base64, の接頭辞や改行は残したままで構いません。
デコードした PDF が破損している、または真っ白なのはなぜですか?
ほとんどの場合、ログの行長制限、データベースのカラム、コピー&ペーストの上限などで文字列が途中で切れ、ファイルの末尾が失われています。完全な PDF は %%EOF で終わります。デコード後のサイズを送信元が示すサイズと比べてみてください。
パスワード付きの PDF も表示できますか?
はい。情報欄に 暗号化:はい と表示され、Chrome や Firefox の内蔵ビューアがプレビュー内でパスワードを尋ねます。ダウンロードしたファイルは元のままなので、同じパスワードで開けます。
Base64 が PDF ではないと表示されるのはなぜですか?
デコードしたバイト列が %PDF- で始まっていないためです。多くの場合、API がドキュメントの代わりにエラーページや JSON のメッセージを返しています。警告には検出された形式が示され、その拡張子で保存して中身を確認することもできます。
機密性の高い PDF をここでデコードしても安全ですか?
PDF はブラウザ内でデコード・表示され、ページの Content Security Policy が Cloudflare のページビュー計測以外のネットワークリクエストをブロックします。ページを読み込んだ後はオフラインにしても使い続けられます。