A PDF は他のファイルを内部に保持できます。契約書やスプレッドシートをまとめたポートフォリオや、ソースデータが添付されたレポートとして使用できます。コードでこれらのファイルを取り出す際、attachment1.bin のような名前ではなく、作者が付けた元の名前で保存したいでしょう。このチュートリアルでは、Aspose.PDF for .NET を使用して C# で PDF から埋め込みファイルを元の名前で抽出する方法を示します。PDF を開き、埋め込みファイルをループで処理し、FileSpecification.GetFileName で各ファイル名を取得し、フォルダーに内容を書き込みます。

PDF が埋め込みファイルの名前を保存する場所

各埋め込みファイルはファイル仕様で記述され、ファイル仕様は名前を複数の場所に記録できます。Unicode ファイル名、標準ファイル名、そしてドキュメントの埋め込みファイルコレクションにリストされているキーがあります。PDF プロデューサーはこれらを一貫して埋めることはなく、名前をまったく省略するものもあります。

Aspose.PDF for .NET はこの問題に対処するために FileSpecification.GetFileName プロパティを提供します。Unicode 名、通常のファイル名、またはコレクションキーのいずれか利用可能なものから名前を解決するため、Unicode 名が欠落している場合でも使用可能な名前が取得できます。名前が全くないファイルに対してはフォールバック名を渡すことができます。オプションの第2パラメータで、ファイル名が利用できない場合に空の名前を許可するかどうかを制御します。PDF 辞書を読み取るための独自ロジックを記述する代わりに、1 回の呼び出しで済みます。

注: この記事の例ではフォールバック引数のみを使用しています。

Document.EmbeddedFiles はドキュメントレベルの添付ファイルを保持し、PDF ポートフォリオ内のファイルを含みます。ファイル添付アノテーション(通常はクリップのアイコンで表示されます)を介して特定のページに添付されたファイルは、代わりにそのアノテーションに保存されます;ページに添付されたファイルを抽出する でそれらについて説明します。

Aspose.PDF を使用して PDF から埋め込みファイルを抽出する

  • .NET プロジェクトです。
  • Aspose.PDF for .NET 26.9 or later、これは FileSpecification.GetFileName を導入したリリースです。 NuGet からインストールしてください:
Install-Package Aspose.PDF

または .NET CLI で:

dotnet add package Aspose.PDF
  • 埋め込みファイルを含む PDF。例では PDFPortfolio.pdf というポートフォリオを使用します。

ライセンスがない場合、Aspose.PDF は評価モードで実行されます。評価制限なしでテストするには、無料の一時ライセンス をリクエストしてください。

元の名前で埋め込まれたすべてのファイルを抽出する

次のメソッドは PDF を開き、埋め込まれた各ファイルを解決された名前で出力フォルダーに保存し、書き込んだ各ファイルのパスを出力します。

using System;
using System.IO;
using Aspose.Pdf;

public static class EmbeddedFileExtractor
{
    public static void ExtractEmbeddedFiles(string inputPdf, string outputDir)
    {
        Directory.CreateDirectory(outputDir);

using (var document = new Document(inputPdf))
        {
            foreach (FileSpecification fileSpec in document.EmbeddedFiles)
            {
                // Resolve the stored name, then keep only the file name part.
                string fileName = Path.GetFileName(fileSpec.GetFileName("attachment.bin"));
                string outputPath = Path.Combine(outputDir, fileName);

using (var output = new FileStream(outputPath, FileMode.Create))
                {
                    fileSpec.Contents.CopyTo(output);
                }

Console.WriteLine($"Saved: {outputPath}");
            }
        }
    }
}

PDF のパスと、ファイルを保存したいフォルダーを指定して呼び出します:

EmbeddedFileExtractor.ExtractEmbeddedFiles("PDFPortfolio.pdf", "ExtractedFiles");

各ステップが何をするか

ドキュメントを開く。 new Document(inputPdf) は PDF をロードします。using ブロックは、例外がスローされた場合でも、処理が完了したときにファイルハンドルを解放します。

添付ファイルをループ処理します。 document.EmbeddedFiles は、ドキュメントレベルの埋め込みファイルごとに 1 つの FileSpecification を返します。

名前を解決します。 fileSpec.GetFileName("attachment.bin") は保存された名前を返します。PDF が名前を提供しない場合は attachment.bin が返されます。アプリケーションに適したフォールバックを選択してください。

フォルダー セグメントを除去する。 保存された名前には reports/2026/q3.xlsx のようなパスや、..\..\startup.bat のように細工された値が含まれることがあります。結果を Path.GetFileName に通すと q3.xlsx または startup.bat に縮小されるため、ファイルは outputDir の外に書き込まれません。たとえ現在処理している PDF を信頼していても、この手順は保持してください。

内容を書き込む。 fileSpec.Contents は埋め込みファイルのデータのストリームです。 CopyTo は変換せずに新しいファイルに書き込みます。

期待される結果

出力フォルダーには、ドキュメントレベルの添付ファイルごとに 1 つのファイルが含まれ、PDF に保存された名前が付けられます。スプレッドシートと Word 文書を保持するポートフォリオの場合、コンソール出力は次のようになります。

Saved: ExtractedFiles\budget-2026.xlsx
Saved: ExtractedFiles\service-agreement.docx

ファイル名は PDF に依存します。抽出されたファイルは埋め込まれたデータと同じ内容を含んでいるため、各ファイルはその形式を処理できるアプリケーションで開きます。

重複および安全でない名前の処理

基本的な例には、実際の PDF で遭遇する 3 つの弱点があります:

  • 2つの添付ファイルが同じ名前を共有でき、FileMode.Create は最初のものを黙って上書きします。名前がない複数の添付ファイルがすべて attachment.bin にフォールバックする場合も同様です。
  • あるオペレーティングシステムで有効な名前でも、別の OS では無効な文字を含むことがあります。たとえば Windows の : です。
  • パス区切り文字で終わる保存された名前は、Path.GetFileName が空文字列を返す原因となります。

このヘルパーは3つすべてを処理します。無効な文字を置き換え、名前が空の場合はフォールバックし、ファイルがすでに存在する場合はカウンタを追加します:

private static string GetSafeOutputPath(string outputDir, string resolvedName, string fallbackName)
{
    string fileName = Path.GetFileName(resolvedName);

foreach (char c in Path.GetInvalidFileNameChars())
    {
        fileName = fileName.Replace(c, '_');
    }

if (string.IsNullOrWhiteSpace(fileName))
    {
        fileName = fallbackName;
    }

string baseName = Path.GetFileNameWithoutExtension(fileName);
    string extension = Path.GetExtension(fileName);
    string outputPath = Path.Combine(outputDir, fileName);

int counter = 1;
    while (File.Exists(outputPath))
    {
        outputPath = Path.Combine(outputDir, $"{baseName} ({counter}){extension}");
        counter++;
    }

return outputPath;
}

抽出ループでは、fileName と outputPath を構築する 2 行を次のように置き換えます:

string outputPath = GetSafeOutputPath(outputDir, fileSpec.GetFileName("attachment.bin"), "attachment.bin");

ヘルパーは既存のファイルをチェックするため、同じフォルダーに抽出を2回実行すると、上書きされずに番号付きのコピーが作成されます。各実行で新しい結果を得たい場合は、最初にフォルダーをクリアしてください。

ページに添付されたファイルを抽出

EmbeddedFiles が空でも PDF ビューアにクリップのアイコンが表示される場合、ファイルはページ上のファイル添付アノテーションを介して添付されている可能性があります。アノテーションは File プロパティに独自の FileSpecification を保持しているため、同じ名前解決と同じヘルパーが適用されます。このメソッドはすべてのページをチェックし、添付された各ファイルを出力フォルダーに保存します:

using Aspose.Pdf.Annotations;

public static void ExtractPageAttachments(string inputPdf, string outputDir)
{
    Directory.CreateDirectory(outputDir);

using (var document = new Document(inputPdf))
    {
        foreach (Page page in document.Pages)
        {
            foreach (Annotation annotation in page.Annotations)
            {
                if (annotation is FileAttachmentAnnotation attachment && attachment.File != null)
                {
                    string outputPath = GetSafeOutputPath(outputDir, attachment.File.GetFileName("attachment.bin"), "attachment.bin");

using (var output = new FileStream(outputPath, FileMode.Create))
                    {
                        attachment.File.Contents.CopyTo(output);
                    }

Console.WriteLine($"Saved: {outputPath}");
                }
            }
        }
    }
}

PDF のすべての添付ファイルを収集するには、同じ出力フォルダーで両方のメソッドを実行します。PDF が両方の場所から同じファイルを参照している場合、GetSafeOutputPath は最初のコピーを上書きせず、2 番目のコピーを番号付きの名前で保存します。

次のステップ

添付ファイルの追加、削除、抽出せずに一覧表示など、さらに詳しく操作したい場合は、Aspose.PDF for .NET ドキュメント を参照してください。FileSpecification クラス リファレンス では、埋め込みファイルごとに読み取れる other name と description プロパティが一覧されています。PDF が期待どおりに抽出されない場合は、Aspose.PDF サポートフォーラム にサンプルを投稿してください。

FAQs

  1. How does FileSpecification.GetFileName choose a name? 埋め込みファイルの Unicode 名、通常のファイル名、またはコレクションキーのいずれか利用可能なものから名前を解決します。利用可能なものがない場合は、渡したフォールバック名を返します。このメソッドは Aspose.PDF for .NET 26.9 で追加されました。

  2. これはポートフォリオではないPDFでも機能しますか? はい、ドキュメントレベルで添付されたファイルについては機能します。特定のページにファイル添付アノテーション(通常はクリップのアイコンで表示されます)を介して添付されたファイルは、アノテーションに保存されるため、FileAttachmentAnnotation.File から読み取ります。詳細は Extract files attached to pages を参照してください。

  3. Why wrap the result of GetFileName in Path.GetFileName? PDF に保存されている名前はファイルを作成した人が設定したもので、フォルダーのセグメントが含まれることがあります。Path.GetFileName はファイル名だけを保持するため、すべての添付ファイルが出力フォルダー内に書き込まれます。

  4. 2つの添付ファイルが同じ名前の場合はどうなりますか? FileMode.Create を使用すると、2番目のファイルが最初のファイルを上書きします。パスが既に存在するか確認し、数値サフィックスを追加してください。詳細は Handle duplicate and unsafe names を参照してください。

  5. ディスクに保存せずに添付ファイルを処理できますか? はい。Contents プロパティは Stream ですので、MemoryStream にコピーしたり、アップロードしたり、FileStream に書き込む代わりに別のライブラリに渡すことができます。