完全な動作例は GitHub で入手できます:
strip-pdf-metadata-dotnet
はじめに
PDF メタデータのサニタイズは、.NET 用 GroupDocs.Metadata のワークフローで、C# サービスから PDF の Info 辞書と XMP 識別フィールドをクリアします。社内ドライブから契約書 PDF が外部に出るとき、Author、Creator、Producer、Keywords、そして XMP パケットが一緒に残ってしまうことがあります。ブラウザのクリーナーや Acrobat での簡単なチェックは成功したように見えても、XMP が元の作者名を保持していることがあります。パートナーが別のビューアでファイルを開いたときに、Alice Example が Author として表示された「クリーン」なドラフトに遭遇したのがこの問題です。
GroupDocs.Metadata for .NET は、同じ Metadata オブジェクトに対して 2 つの明確なクリーンアップ強度を提供します。検出されたパッケージをすべて削除する Sanitize() と、Title と Subject は残しつつ人物情報だけを除去する RemoveProperties です。本稿では、結果を監査可能にする検査と検証の手順とともに、両アプローチを比較します。
この記事を読めば、.NET 8 のサンプルコード、外部向けとアーカイブ向けのクリーンアップを選択する判断基準、そして Save 後に Author / Person.Creator をチェックする検証述語が手に入ります。
PDF メタデータのクリーンアップが重要な理由
外部ファイル共有、マルチテナントのダウンロード、規制対象のアーカイブは、デスクトップのクリック操作ではなく、繰り返し可能なメタデータ除去 API を必要とします。このアプローチが特に有用になるシーンは次のとおりです。
- パートナーポータル: PDF が信頼境界を越える前に完全に削除
- レコード検索: Title/Subject は残しつつ Author 系フィールドだけを除去
- インシデント対応: 誤って共有した後に Author が消えていることを証明
- CI ゲート: 検証が false を返したらビルドを失敗させる
「メタデータを削除する」という一行ポリシーだけでは、Sanitize と選択的除去の違いが隠れてしまいます。コードレビューで強度を明示すれば、アーカイブが必要とする Keywords が無意識に削除されるリスクを防げます。
前提条件
開始する前に以下を用意してください。
- .NET 8 SDK
- GroupDocs.Metadata 26.8.0(一時ライセンス)
- Info 辞書や XMP 識別フィールドが残っている PDF
- Visual Studio 2022 または VS Code(任意)
インストール
NuGet で GroupDocs.Metadata をインストールします。
dotnet add package GroupDocs.Metadata --version 26.8.0
またはサンプルプロジェクトの .csproj から復元してください。Save を制限なしで行うには、環境変数 LIC_METADATA_VALID を GroupDocs.Metadata.Product.Family.lic が格納されたフォルダーに設定します。
方法 1 – クリーン前に検査する
まず読み取り専用で一覧を取得し、PDF が実際にどのフィールドを保持しているかを把握します。ブラウザツールは XMP を見逃すことが多く、この一覧が「ビフォー/アフター」チェックの基準になります。
using var metadata = new Metadata(inputPath);
var properties = metadata.FindProperties(p =>
p.Tags.Contains(Tags.Person.Creator) ||
p.Tags.Contains(Tags.Tool.Software) ||
p.Tags.Contains(Tags.Content.Title) ||
p.Tags.Contains(Tags.Content.Subject) ||
string.Equals(p.Name, "Author", StringComparison.OrdinalIgnoreCase) ||
string.Equals(p.Name, "Creator", StringComparison.OrdinalIgnoreCase) ||
string.Equals(p.Name, "Producer", StringComparison.OrdinalIgnoreCase) ||
string.Equals(p.Name, "Keywords", StringComparison.OrdinalIgnoreCase));
foreach (var property in properties)
{
Console.WriteLine($"{property.Name} = {property.Value}");
}
重要ポイント
- タグと名前の併用: フィールドをタグ付けする方式が異なるプロデューサーにも対応できるよう、
Author/Keywordsの文字列比較を組み合わせます - 変更なし: ドライランやサポートチケットで安全に使用可能
- フィルタの再利用: 後の除去述語でも同じ考え方を流用できます
方法 2 – 検出されたメタデータをすべてサニタイズ
PDF に作者情報の痕跡を残したくない場合は Sanitize() を使用します。この呼び出しは、Info 辞書のフィールドと XMP を含む認識されたパッケージをすべてクリアし、続いて新しいファイルを保存します。
using var metadata = new Metadata(inputPath);
int removed = metadata.Sanitize();
Console.WriteLine(removed);
metadata.Save(outputPath);
重要ポイント
- ワンコール: 外部向けルートでの表面積が小さい
- 削除件数をログに: 事前にクリーンな入力か、大規模な削除が行われたかをオペレーターが把握できる
- ツールスタンプに注意:
Save後、Creator/Producer が PDF エンジンのTool.Software値になることがあります
適用シーン: パートナーのダウンロード、公開リンク、テナント間の交換
方法 3 – 作者系プロパティだけを除去
Title、Subject、Keywords が検索に必要な場合は、RemoveProperties を使って人物情報だけを除去します。すべてのパッケージを削除するわけではありません。
using var metadata = new Metadata(inputPath);
int removed = metadata.RemoveProperties(p =>
p.Tags.Contains(Tags.Person.Creator) ||
p.Tags.Contains(Tags.Person.Editor) ||
string.Equals(p.Name, "Author", StringComparison.OrdinalIgnoreCase) ||
string.Equals(p.Name, "Creator", StringComparison.OrdinalIgnoreCase) ||
string.Equals(p.Name, "Producer", StringComparison.OrdinalIgnoreCase));
Console.WriteLine(removed);
metadata.Save(outputPath);
重要ポイント
- 述語がレビュー可能: コードレビューでどの人物情報が削除されるかが一目で分かる
- 記述的フィールドは残る: Title/Subject/Keywords はこのサンプルフィルタで保持される
- 同一 SDK: 選択的パス用に別ライブラリは不要
適用シーン: 社内アーカイブ、ドラフトの循環、Author を禁止し Keywords は許可するポリシー
Save 後に Author 除去をどう証明するか?
クリーンした PDF を再度開き、Author / Person.Creator / Person.Editor のみを検索します。残っていなければ True を出力します。Save 後に残る Creator/Producer の Tool.Software フィンガープリントは失敗とみなさないでください。Save が PDF エンジン名でそれらを書き換えることがあるためです。この区別が CI でのコンプライアンスチェックを正しく保ち、エンジンが自分のツールフィールドをスタンプしたときの誤警報を防ぎます。
using var metadata = new Metadata(inputPath);
var leftovers = metadata.FindProperties(p =>
p.Tags.Contains(Tags.Person.Creator) ||
p.Tags.Contains(Tags.Person.Editor) ||
string.Equals(p.Name, "Author", StringComparison.OrdinalIgnoreCase));
Console.WriteLine(!leftovers.Any());
重要ポイント
- 正しい質問をする: 「Author が無くなったか?」であって「Creator が空か?」ではない
- 二度目のオープン:
Save後に検証し、メモリ上だけでなく実ファイルでも確認 - CI フレンドリー: テストやログで使えるブール値が 1 つだけ
Sanitize と RemoveProperties の選択基準
| 質問 | Sanitize を推奨 | RemoveProperties を推奨 |
|---|---|---|
| ファイルが社外へ出るか | はい | 説明フィールドが残る必要がある場合のみ |
| アーカイブ検索で Title が必要か | いいえ | はい |
| ポリシーで「メタデータに人物情報は入れない」か | どちらでも、検証で確認 | はい(人物指向の述語で) |
| オペレーターがワンボタンを求めるか | はい | 名前付きルートの背後にラップ可能 |
strip-pdf-metadata-dotnet は、Resources/contract-with-metadata.pdf に対して 4 つのステップ(検査、サニタイズ、選択的除去、検証)をすべて実行する実行可能な .NET デモです。
よくあるミス
- ブラウザクリーナーだけに頼る: XMP は残りやすい
- Creator/Producer 名を検証対象にする:
Save後のエンジンフィンガープリントで偽陽性になる - 同じ述語を永遠に使い回す: 新しいプロデューサーが出たらフィールド名を見直す
- Save 用のライセンス設定を省く: 評価モードでは無制限書き込みがブロックされる。フルパイプラインテストのために
LIC_METADATA_VALIDを設定すること - 検査を省く: ビフォー一覧がなければ、Sanitize が 7 フィールド削除したのか 0 フィールド削除したのか判断できない
サンプルの contract-with-metadata.pdf では、ライセンス付き実行で通常、検査時に Author と Keywords が表示され、Sanitize の削除件数は約 7、Author に焦点を当てた検証は True を出力します。選択的作者除去は件数が約 3 と少なく、Title と Subject は二度目の検査で残っていることが確認できます。
追加リソース
- ユースケース: PDF メタデータのサニタイズ vs 作者除去 (.NET)
- ドキュメント: 検出されたすべてのメタデータパッケージを除去
- ドキュメント: 特定のメタデータプロパティを除去
- GitHub: strip-pdf-metadata-dotnet
- API リファレンス
結論
.NET における PDF メタデータのクリーンアップは、曖昧な名前の単一 API 呼び出しではありません。外部向けの徹底削除には Sanitize()、Title と Subject を残したい場合は RemoveProperties を選び、常に Save 後に Author 系フィールドを検査・検証してください。サンプルリポジトリをクローンし、シードされた契約 PDF で実行した後、同じ手法をアップロードサービスに組み込み、削除件数のロギングを忘れずに行いましょう。