PDFsharpガイド:MigraDocとPdfSharpCoreを使用してPDFファイルを作成する
PDFsharpは、C#コードからPDFドキュメントを作成・編集するためのオープンソースの.NETライブラリです。ページにテキスト、線、画像を描画し、保存メソッドを呼び出すだけで、PDFファイルが作成されます。ブラウザエンジンもネイティブバイナリも必要ありません。このプロジェクトは2005年に始まり、現在でも.NETバックエンドから生成される請求書、レポート、証明書の多くはPDFsharpを経由しています。
この記事は、サーバー上でPDFファイルが必要な開発者向けに、その使い方を詳しく解説したものです。PDFsharpとMigraDocの連携方法、インストールすべきビルド、最初の動作ファイル、Linuxにおけるフォントの問題、最近のライセンス変更、そして別のソフトウェアを選択すべきタイミングについて解説します。
PDFsharpとは何ですか?また、どのようなことができますか?
PDFsharpライブラリの背後には、20年近くにわたってこのライブラリを存続させてきたドイツの小さな会社、empira Software GmbHがあります。ほとんどの時間はXGraphicsというクラスに費やされます。System.Drawing.Graphicsを使ってWinFormsで描画したことがある人なら、10分以内に馴染めるでしょう。フォント、ブラシ、xとyを指定して、さあ始めましょう。
箱から出してすぐに使えるもの:
- テキスト、ベクター図形、線、画像を使って、PDFドキュメントをゼロから作成します。
- 既存のPDFファイルを開き、スタンプ、透かし、ページ番号などのコンテンツをページに追加します。
- あるファイルから別のファイルにページをインポートして、ドキュメントを結合および分割します。
- フォントを埋め込んでサブセット化することで、どのマシンでもファイルが同じように見えるようにします。
- ブックマーク、リンク、タイトル、著者、キーワードなどのドキュメントメタデータを追加します。
- パスワードとアクセス権限フラグを使用してファイルを保護する
- 文書への電子署名に対応(バージョン6.2以降)
デプロイは退屈です。これは褒め言葉です。すべてがマネージドコードなので、運用担当者がサーバーにヘッドレスChromeをインストールしたり、午前2時にGhostscriptのDLLを探し回ったりする必要は一切ありません。NuGetパッケージを1つ参照してプッシュするだけで完了です。
さて、落とし穴があります。得られるのはキャンバスだけで、それ以上のものは何も提供されません。長い段落が下余白に当たってしまう?それはあなたの責任です。表が1ページ目を超えて表示される?それもあなたの責任です。MigraDocを導入しない限りは。
PDFsharpとMigraDoc:どちらのレイヤーが必要ですか?
同じベンダー、同じリリーススケジュールでも、仕事内容は全く異なります。MigraDoc FoundationはPDFsharpの1階上に位置しています。文字列の配置場所を指定するのではなく、セクション、段落、表、ヘッダー、フッター、スタイル、そして時折挿入されるグラフなどを渡すと、MigraDoc Foundationがそれらをすべて適切な場所に配置してくれます。そして、PDFファイルが生成されます。あるいは、何でもWordで開きたいという同僚のためにRTFファイルも用意されています。
私の略記法はこうです。PDFsharpは「このテキストをx=40、y=120の位置に配置する」。MigraDocは「ここに30行と繰り返しのヘッダーがあるので、ページを並べ替えてください」。
| タスク | 最適なフィット感 | なぜ |
|---|---|---|
| 固定位置が記載された1ページの証明書またはチケット | PDFsharp | すべての座標を完全に制御できます |
| 表とヘッダーを含む複数ページのレポート | MigraDoc | 自動ページネーションとスタイル |
| 明細項目数が可変の請求書 | MigraDoc | 表はページをまたいで拡大したり分割されたりする。 |
| 既存のPDFにスタンプ、透かし、またはページ番号を付ける | PDFsharp | MigraDocは新しいドキュメントを作成するだけです |
| 既存のファイルを結合または分割する | PDFsharp | ページインポートはPDFsharpの機能です |
| レポート内のビジネスチャート | MigraDoc | チャートサポート機能を内蔵 |
| 混合:生成されたレポートとカスタムデザインの表紙 | 両方 | MigraDoc は PDFsharp ページにレンダリングできます |
実際のプロジェクトでは、結局両方を使うことになることが多い。MigraDoc で本文を作成し、下のレイヤーでベンダーの PDF に手描きの表紙やスタンプを押すといった具合だ。いずれにせよ、PDFsharp のインストールは避けられない。MigraDoc パッケージが依存関係として PDFsharp を組み込むからだ。
PDFsharpビルドの説明:コアビルド、GDI+、WPF
新規ユーザーはNuGetのパッケージリストで次に行き詰まることが多い。PDFsharp 6には3つのビルドがあり、それぞれにMigraDocのペアが付属している。
| NuGetパッケージ | 建てる | プラットフォーム | フォントと画像 |
|---|---|---|---|
| PDFsharp / PDFsharp-MigraDoc | コア | Windows、Linux、macOS | フォントリゾルバーが必要です。BMP、PNG、JPEG画像に対応。 |
| PDFsharp-GDI / PDFsharp-MigraDoc-GDI | GDI+ | Windowsのみ | System.Drawing を介してインストール済みのフォントを使用します |
| PDFsharp-WPF / PDFsharp-MigraDoc-WPF | WPF | Windowsのみ | WPF経由でインストール済みのフォントを使用する |
現在のパッケージは、.NET 8、9、10に加え、.NET Standard 2.0および.NET Framework 4.6.2を対象としています。そのため、古いWinFormsツールから最新のASP.NET Core APIまで、現在開発中のほぼすべてのものがカバーされています。
コンソールアプリ、Web API、Docker、Azure Functions、Linux 上のあらゆるもの?コアビルド。GDI+ や WPF は、システムフォントやネイティブコントロールでのプレビューが必要な Windows デスクトップアプリの場合にのみ意味があります。Stack Overflow で、コンソールアプリに WPF バージョンが必要かどうかを尋ねた人がいましたが、必要ありませんでした。

Visual StudioでNuGetからPDFsharpをインストールする方法
WinForms時代のフォーラム投稿の中には、ZIPファイルをダウンロードしてDLLを探し出し、自分で参照を追加するように指示しているものもまだ見かけますが、それらは無視してください。PDFsharpはNuGet経由でインストールしてください。パッケージマネージャーがバージョン管理をしてくれるので、自分でバージョン管理をする必要はありません。
- Visual Studioでソリューションを開き、ソリューションエクスプローラーでプロジェクトを右クリックします。
- 「NuGet パッケージの管理」を選択し、 「参照」タブに切り替えて、「PDFsharp」を検索します。
- ドキュメントのレイアウト機能も必要な場合は、 PDFsharp (コアビルド)またはPDFsharp-MigraDocを選択してください。発行元がempira Software GmbHであることを確認してください。
- 「インストール」をクリックし、ライセンス認証のプロンプトに同意してください。
- パッケージが正しく復元されたことを確認するために、プロジェクトを一度ビルドしてください。
端末ユーザーはクリック操作を省略できます。
bash dotnet add package PDFsharp dotnet add package PDFsharp-MigraDoc
パッケージ マネージャー コンソール内では、同じコマンドとして Install-Package PDFsharp を実行します。また、ビルドを混在させないようにしてください。あるプロジェクトが PDFsharp を参照し、その隣のプロジェクトが PDFsharp-GDI を取り込んだために、型競合が発生し、チームが丸一日を無駄にした事例を私は見てきました。
PDFsharp を使用した最初の PDF ドキュメント (C 言語)
以下は、1ページのPDFファイルを生成する最小規模のプログラムです。フォントリゾルバが設定されていれば(次のセクションを参照)、どのOSのCoreビルドでも動作します。
```csharp
PdfSharp.Drawing を使用します。
PdfSharp.Pdf を使用します。
// PDFsharp 6.5以降では、初回使用前にライセンスを選択する必要があります。
PdfSharpLicense.SetAgplLicense();
var document = new PdfDocument();
document.Info.Title = "こんにちは PDFsharp";
PdfPage page = document.AddPage();
XGraphics gfx = XGraphics.FromPdfPage(page);
var font = new XFont("Arial", 20, XFontStyleEx.Bold);
gfx.DrawString("こんにちは、PDFsharp!", font, XBrushes.Black,
新しい XRect(0, 0, page.Width.Point, page.Height.Point)
XStringFormats.Center);
document.Save("hello.pdf");
「`」
PDFsharpのすべてのプログラムは、ドキュメント、ページ、XGraphics、描画、保存という流れに従います。単位はポイント(1/72インチ)で、原点は左上隅にあります。6.2.xでは、ライセンス行を削除してください。このAPIは6.5.0で初めて登場しました。
そしてMigraDoc版:
```csharp
MigraDoc.DocumentObjectModel を使用します。
MigraDoc.Rendering を使用します。
var doc = new Document();
Section section = doc.AddSection();
section.AddParagraph("こんにちは、MigraDoc!");
var renderer = 新しい PdfDocumentRenderer { Document = doc };
レンダラー.RenderDocument();
renderer.PdfDocument.Save("hello-migradoc.pdf");
「`」
座標はどこにもありません。500段落を投入すれば、ページネーションコードが一切ないまま、必要なページ数だけ表示されます。
PDFsharpコアビルドにおけるフォント:リゾルバーの問題
周囲に聞いてみると、フォントに関する不満が最も多く聞かれるでしょう。GDI+ および WPF ビルドは、Windows にインストールされている TrueType フォントを読み込むだけです。一方、Core ビルドは何も想定できません。なぜなら、軽量な Linux コンテナには、使用可能なフォントがまったく含まれていないことが多いからです。そのため、最初の Docker デプロイは、適切なフォントが見つからないという例外で終了する傾向があります。
解決策は、IFontResolver インターフェースを実装するフォントリゾルバーというクラスを作成することです。このクラスには次の 2 つのメソッドがあります。
- ResolveTypefaceは、要求されたフォントファミリーとスタイル(例えば「Arial」、太字)をフォント名にマッピングします。
- GetFontは、指定されたフォント名のTTFファイルの生バイトを返します。
最初の XFont が作成される前に、起動時に GlobalFontSettings.FontResolver を介して一度登録してください。
```csharp
public class AppFontResolver : IFontResolver
{
public FontResolverInfo? ResolveTypeface(string family, bool bold, bool italic)
=> new FontResolverInfo(bold ? "Inter-Bold" : "Inter-Regular");
public byte[]? GetFont(string faceName) => File.ReadAllBytes(Path.Combine(AppContext.BaseDirectory, "Fonts", faceName + ".ttf"));
}
GlobalFontSettings.FontResolver = new AppFontResolver();
「`」
自分でぶつける前に知っておくべき重要なこと:
- プロジェクト内の Fonts フォルダーに TTF ファイルを保存し、出力ディレクトリにコピーするように設定するか、リソースとして埋め込んでコンテナイメージに常に含まれるようにしてください。
- バージョン6.2.0では、古いCoreBuildFontResolverが削除されました。WindowsまたはWSL2では、GlobalFontSettings.UseWindowsFontsUnderWindowsを使用することで同様の動作を復元できますが、LinuxまたはmacOSでは何も効果がありません。
- 公式サンプルリポジトリには、出発点としてコピーできるSubstitutingFontResolverが含まれています。
- 商用フォントを生成ファイルに埋め込む前に、フォントのライセンスを確認してください。Inter、Roboto、Notoなどのオープンフォントであれば、この問題は発生しません。
リゾルバーを導入すると、Windows、Linux、macOS のいずれの環境でも出力結果が同一になります。
PDFsharp 6 を使用したファイルの結合、署名、およびセキュリティ保護
多くのチームは、文書をゼロから作成することはありません。ライブラリを使用して、既存のファイルを結合、スタンプ、またはロックします。マージは数行のコードで済みます。各ソースをインポートモードで開き、ページをコピーするだけです。
csharp var output = new PdfDocument(); foreach (var path in new[] { "part1.pdf", "part2.pdf" }) { using var input = PdfReader.Open(path, PdfDocumentOpenMode.Import); foreach (PdfPage p in input.Pages) output.AddPage(p); } output.Save("merged.pdf");
分割処理は、同じループを逆方向に実行したもので、ページまたは範囲ごとに1つの出力ファイルが生成されます。セキュリティ保護のため、document.SecuritySettingsには、ユーザーパスワード、所有者パスワード、およびアクセス許可フラグ(印刷、テキストのコピーなど)を指定できます。
長らく要望されていた2つの機能が、ついにバージョン6.2に搭載されました。
- CMS に基づくデジタル署名。デフォルトの署名機能は、別の PDFsharp.Cryptography アセンブリに同梱されています。独自の署名機能を追加するには、IDigitalSigner を実装してください。タイムスタンプサーバーのサポートは、最新の .NET では動作しますが、.NET Framework ビルドでは動作しません。
- アーカイブ用のPDF/A出力。公式ドキュメントでは「いくつかの制限付き」でまだ開発中と記載されているため、コンプライアンス準拠のために使用する前に、PDF/Aチェッカーで結果を検証してください。
このリリースでは、カラー絵文字グリフとマネージドMD5実装も導入されました。これは、FIPSルールに基づいて実行する場合やBlazorで実行する場合に重要です。
PDFsharpリポジトリ、PdfSharpCoreフォーク、および1.xバージョン
GitHubで「PDFsharp」を検索すると、ほぼ同じ名前のプロジェクトがいくつか見つかります。これは歴史のせいでしょう。
旧バージョンの1.x系(1.50、1.51)は.NET Frameworkでしか動作しませんでした。.NET Coreが登場した際、人々は待つことを嫌い、独自に移植を行いました。Stefan Steiger氏が開発を開始し、後に他のフォークに引き継がれたPdfSharpCoreは、多くの人が知っているものです。これはGDI+を排除し、公式リリースより何年も早くLinux上で動作するようにしました。
そしてPDFsharp 6が登場した。これは最新の.NETで本格的に書き直され、公式のクロスプラットフォームCoreビルドが提供された。これにより、フォーク版は存在意義のほとんどを失った。
| プロジェクト | メンテナー | プラットフォーム | 状態 |
|---|---|---|---|
| PDFsharp 6.x (empira/PDFsharpリポジトリ) | empira Software GmbH | .NET 8~10、.NET Standard 2.0、.NET Framework 4.6.2 | 積極的に維持管理されています |
| PDFsharp 1.5倍 | empira Software GmbH | .NET Frameworkのみ | ソースコードはGitHubに保存されていますが、現在はメンテナンスされていません。 |
| PdfSharpCoreとその派生版 | コミュニティ | .NET Core / .NET Standard 2.0 | フォークによって異なり、更新速度が遅い |
| PDFsharp-MigraDoc 6.x | empira Software GmbH | PDFsharp 6と同じ | 積極的に維持管理されています |
さて、Redditでよく見かける「PdfSharp vs PdfSharpCore」のスレッドについてですが、新しいプロジェクトとして公式パッケージを用意しましょう。古いコードが既にフォークに依存していて、今すぐ移行する価値がない場合のみ、フォークを保持してください。ドキュメントが不十分だと感じたら、empiraのサンプルリポジトリを参照しましょう。フォルダとファイルは実行可能なサンプルなので、推測するよりはるかに効率的です。
PDFsharpは無料ですか? PDFsharp 6.5のライセンス変更点
そのほとんどの期間、そうでした。MITライセンスだったので、ほぼ制約なしで商用利用できました。バージョン6.2.4までのすべてのリリースは現在もそうです。
バージョン6.5.0で変更されました。ライブラリは現在、デュアルライセンスとなっています。
- AGPL(無料)。ライブラリを使用する前に、PdfSharpLicense.SetAgplLicense() を呼び出すことで有効にできます。AGPLでは、ネットワーク経由でソフトウェアとやり取りするユーザーを含む、すべてのユーザーにソースコードを公開することが求められるため、クローズドソースのSaaSには適していません。
- 商用ライセンス。ベンダーからライセンスキーを購入し、PdfSharpLicense.LoadLicense(...) でロードします。これにより、AGPLの義務が解除されます。
バージョン6.5.0以降では、コード内で明示的にどちらかを選択する必要があります。7.0のプレビュー版も同様です。
実際には:
- AGPLと互換性のあるオープンソースプロジェクトは、最新バージョンを無料で引き続き使用できます。
- クローズドソース製品は、商用ライセンスを購入するか、MITライセンスのまま6.2.xバージョンを使い続けるかのどちらかを選択できます。現状維持を選択すると、将来の修正を受けられなくなるため、そのコストをよく検討してください。
- いずれを選択するにしても、必ずライセンス条項をよく読み、法務チームの承認を得てください。このガイドは法的助言ではありません。

PDFsharpの欠点と、それと組み合わせるべきもの
図書館はきちんと役割を果たしている。ただ、その役割が限定的で、どのフォーラムのスレッドでも同じような欠点が指摘される。
- HTMLからPDFへの変換はできません。PDFsharpはHTMLやCSSをレンダリングしません。コミュニティアドオンのHtmlRenderer.PdfSharpは存在しますが、HTML 4.01とCSSレベル2のみをサポートしているため、フレックスボックスやグリッドを使用した最新のレイアウトは表示されません。HTMLテンプレートが必要なチームは、通常、代わりにヘッドレスブラウザレンダラーを使用します。
- JavaScriptは使用できません。クライアント側で作成されたグラフやコンテンツはキャプチャできません。
- 画像へのレンダリングはできません。PDFsharpでは、PDFページをサムネイルやプレビュー用のPNG画像に変換することはできません。そのためには、別途ラスタライザーが必要です。
- テキスト抽出機能は限定的です。コンテンツストリームを走査することはできますが、位置情報付きのクリーンなテキストを返す高レベルAPIはありません。テキストの読み取りと抽出に特化したオープンソースライブラリであるPdfPigは、別途提供されています。
- フォームのサポートは部分的です。シンプルなAcroFormへの入力は可能ですが、スクリプトを含む複雑なフォームは別問題です。
- 表にはMigraDocが必要です。通常のPDFsharpでは、各行の高さを自分で計算する必要があります。
だからといって悪い選択肢というわけではありません。請求書、明細書、ラベル、証明書といったデータ駆動型の文書はまさにこのツールの得意分野であり、フットプリントも非常に小さいです。しかし、ウェブページのピクセル単位での完璧なコピーはそうはいきません。
暗号通貨の請求書と領収書に対応したPDFsharp
PDFsharpで作成する最も一般的なものは、おそらく領収書でしょう。暗号通貨の領収書は、カードの領収書よりも少し扱いが複雑です。しかし朗報です。決済ゲートウェイがWebhook(支払いステータスが切り替わったときに送信されるHTTPコールバック)に到達すると、すべてのデータが揃います。他に調べる必要はありません。
私が1つに載せるとしたら:
- 注文または請求書のIDと販売者の詳細情報
- 支払い時点における仮想通貨建ての金額とその法定通貨相当額
- コインとネットワーク(例:TRON上のUSDTとEthereum上のUSDT)
- トランザクションハッシュ。顧客はブロックエクスプローラーでそれを検証できます。
- 短縮された受取ウォレットアドレスと確認時間
- 取引または請求書ページにリンクするQRコード
ハッシュ値や住所には等幅フォントを使用してください。顧客は文字を1文字ずつ目を凝らして読むため、Arialフォントではゼロと大文字のOがそっくりに見えてしまいます。ハッシュ値が長すぎる場合は折り返してください。6ptのテキストでは意味がありません。フォントを埋め込み、注文書と一緒にファイルを保存し、会計士から領収書を求められた場合は署名してください。
これまでの説明では、実際にお金を受け取る部分はカバーされていません。その部分には、 Plisioのようなゲートウェイを組み込みます。PlisioはBTC、USDT、その他多くの仮想通貨を受け付け、請求書を作成し、ステータスが変更されるたびにエンドポイントを呼び出します。ハンドラーはペイロードをMigraDocに渡し、購入者はサンキューページにいる間に、あなたのロゴが入った領収書を受け取ります。
結論
私がPDFsharpを使い続ける理由はただ一つ、サイズが小さく、邪魔にならないからです。Coreビルドは.NETが動作する環境であればどこでも実行でき、キャンバスだけではレイアウトが不十分な場合はMigraDocがレイアウト処理を引き継ぎます。最初に決めておくべきことは3つあります。どのビルドを使用するか、フォントをどのように読み込むか、そして6.5以降はAGPLライセンスになったので、どのライセンスを使用するかです。Webページではなくデータを印刷すれば、何年も使い続けることができます。