A PDF สามารถบรรจุไฟล์อื่น ๆ ไว้ภายในได้ มันอาจเป็นพอร์ตโฟลิโอที่รวมสัญญาและสเปรดชีต หรือรายงานที่มีข้อมูลต้นฉบับแนบมา เมื่อคุณดึงไฟล์เหล่านั้นออกในโค้ด คุณต้องการให้แต่ละไฟล์ถูกบันทึกด้วยชื่อที่ผู้เขียนตั้งไว้ ไม่ใช่ attachment1.bin บทแนะนำนี้แสดงวิธีการสกัดไฟล์ที่ฝังอยู่จาก PDF พร้อมชื่อเดิมใน C# โดยใช้ Aspose.PDF for .NET. คุณจะเปิด PDF, วนลูปผ่านไฟล์ที่ฝังอยู่, แก้ไขชื่อไฟล์แต่ละไฟล์ด้วย FileSpecification.GetFileName, และเขียนเนื้อหาไปยังโฟลเดอร์.

ที่ PDF เก็บชื่อของไฟล์ที่ฝังอยู่

แต่ละไฟล์ที่ฝังอยู่จะถูกอธิบายโดยสเปคไฟล์ และสเปคไฟล์สามารถบันทึกชื่อได้ในหลายตำแหน่ง มีชื่อไฟล์แบบ Unicode, ชื่อไฟล์มาตรฐาน, และคีย์ที่ไฟล์ถูกระบุในคอลเลกชันไฟล์ที่ฝังอยู่ของเอกสาร ผู้ผลิต PDF ไม่ได้กรอกข้อมูลเหล่านี้อย่างสม่ำเสมอ และบางคนก็ละเว้นชื่อออกไปทั้งหมด

Aspose.PDF for .NET ให้ FileSpecification.GetFileName property เพื่อจัดการกับเรื่องนี้ มันจะดึงชื่อจากชื่อ Unicode, ชื่อไฟล์ปกติ หรือคีย์ของคอลเลกชัน whichever มีอยู่ ดังนั้นคุณยังคงได้ชื่อที่ใช้งานได้เมื่อชื่อ Unicode หายไป คุณสามารถส่งชื่อสำรองสำหรับไฟล์ที่ไม่มีชื่อเลยได้ พารามิเตอร์ตัวที่สองที่เป็นตัวเลือกจะควบคุมว่าชื่อว่างเปล่าถูกอนุญาตหรือไม่เมื่อไม่มีชื่อไฟล์ คุณจะได้การเรียกหนึ่งครั้งแทนการเขียนตรรกะของคุณเองสำหรับการอ่านพจนานุกรม PDF.

หมายเหตุ: ตัวอย่างในบทความนี้ใช้เพียงอาร์กิวเมนต์ fallback เท่านั้น.

Document.EmbeddedFiles เก็บไฟล์แนบระดับเอกสาร ซึ่งรวมถึงไฟล์ในพอร์ตโฟลิโอ PDF ไฟล์ที่แนบกับหน้าเฉพาะผ่านคำอธิบายการแนบไฟล์ (โดยปกติจะแสดงเป็นไอคอนคลิปหนีบกระดาษ) จะถูกจัดเก็บบนคำอธิบายนั้นแทน; ดึงไฟล์ที่แนบกับหน้า ครอบคลุมส่วนนี้

การใช้ Aspose.PDF เพื่อดึงไฟล์ที่ฝังอยู่จาก PDF

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 ส่งคืน FileSpecification หนึ่งรายการสำหรับไฟล์แนบระดับเอกสารแต่ละไฟล์.

แก้ไขชื่อ. fileSpec.GetFileName("attachment.bin") คืนชื่อที่จัดเก็บไว้ หรือ attachment.bin หาก PDF ไม่ได้ให้ค่าใดๆ เลือกวิธีสำรองที่เหมาะสมกับแอปพลิเคชันของคุณ

ลบส่วนของโฟลเดอร์. ชื่อที่จัดเก็บอาจรวมเส้นทางเช่น reports/2026/q3.xlsx หรือค่าที่สร้างขึ้นเช่น ..\..\startup.bat. การส่งผลลัพธ์ผ่าน Path.GetFileName จะทำให้เหลือเป็น q3.xlsx หรือ startup.bat ดังนั้นไฟล์จะไม่สามารถเขียนออกนอก outputDir ได้. ควรรักษาขั้นตอนนี้ไว้แม้คุณจะเชื่อถือ PDF ที่คุณประมวลผลในวันนี้.

เขียนเนื้อหา. fileSpec.Contents คือสตรีมของข้อมูลไฟล์ที่ฝังอยู่. CopyTo เขียนมันไปยังไฟล์ใหม่โดยไม่มีการแปลงใดๆ.

ผลลัพธ์ที่คาดหวัง

โฟลเดอร์ผลลัพธ์จะมีไฟล์หนึ่งไฟล์สำหรับแต่ละไฟล์แนบระดับเอกสาร โดยตั้งชื่อตามที่ถูกจัดเก็บใน PDF สำหรับพอร์ตโฟลิโอที่มีสเปรดชีตและเอกสาร Word ผลลัพธ์ในคอนโซลจะคล้ายกับนี้:

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

ชื่อไฟล์ขึ้นอยู่กับ PDF ของคุณ ไฟล์ที่ถูกแยกออกมามีข้อมูลเดียวกันกับที่ฝังอยู่ ดังนั้นแต่ละไฟล์จะเปิดด้วยแอปพลิเคชันที่รองรับรูปแบบของมัน

จัดการชื่อที่ซ้ำซ้อนและไม่ปลอดภัย

ตัวอย่างพื้นฐานมีจุดอ่อนสามประการที่คุณจะพบกับ PDF ในโลกจริง:

  • Two attachments can share a name, and FileMode.Create silently overwrites the first one. This also happens when several attachments have no name and all fall back to attachment.bin.
    สองไฟล์แนบอาจมีชื่อเดียวกัน และ FileMode.Create จะเขียนทับไฟล์แรกโดยไม่มีการแจ้งเตือน สิ่งนี้ยังเกิดขึ้นเมื่อไฟล์แนบหลายไฟล์ไม่มีชื่อและทั้งหมดใช้ค่าเริ่มต้นเป็น attachment.bin.

  • A name that is valid on one operating system can contain characters that are invalid on another, such as : on Windows.
    ชื่อที่ใช้ได้บนระบบปฏิบัติการหนึ่งอาจมีอักขระที่ไม่ถูกต้องบนระบบอื่น เช่น : บน Windows.

  • A stored name that ends with a path separator leaves Path.GetFileName with an empty string.
    ชื่อที่จัดเก็บแล้วลงท้ายด้วยตัวคั่นเส้นทางทำให้ Path.GetFileName คืนค่าเป็นสตริงว่าง.

ตัวช่วยนี้จัดการทั้งสามกรณี มันจะแทนที่อักขระที่ไม่ถูกต้อง, ใช้ค่าเริ่มต้นเมื่อชื่อว่างเปล่า, และเพิ่มตัวนับเมื่อไฟล์มีอยู่แล้ว:

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 ด้วย:

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

เนื่องจากตัวช่วยตรวจสอบไฟล์ที่มีอยู่แล้ว การทำการสกัดข้อมูลสองครั้งในโฟลเดอร์เดียวกันจะสร้างสำเนาที่มีหมายเลขแทนการเขียนทับ หากต้องการผลลัพธ์ใหม่ในแต่ละครั้ง ให้ล้างโฟลเดอร์ก่อน

ดึงไฟล์ที่แนบกับหน้า

หาก EmbeddedFiles ว่างเปล่า แต่คุณเห็นไอคอนคลิปกระดาษในโปรแกรมดู PDF ไฟล์นั้นอาจถูกแนบผ่านคำอธิบายการแนบไฟล์บนหน้า คำอธิบายดังกล่าวถือ FileSpecification ของตนเองในคุณสมบัติ File ดังนั้นการแก้ไขชื่อและตัวช่วยเดียวกันจะถูกใช้ วิธีนี้จะตรวจสอบทุกหน้าและบันทึกไฟล์ที่แนบแต่ละไฟล์ไปยังโฟลเดอร์ผลลัพธ์:

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 จะบันทึกสำเนาที่สองด้วยชื่อที่มีหมายเลขแทนการเขียนทับไฟล์แรก.

ขั้นตอนต่อไป

หากต้องการทำงานต่อกับไฟล์แนบ เช่น การเพิ่ม, การลบ หรือการแสดงรายการโดยไม่ต้องแยกไฟล์ออก, ดูเอกสาร เอกสาร Aspose.PDF for .NET. อ้างอิงคลาส FileSpecification แสดงรายการคุณสมบัติชื่ออื่นและคำอธิบายที่คุณสามารถอ่านจากแต่ละไฟล์ที่ฝังไว้. หาก PDF ไม่ได้แยกออกตามที่คาดหวัง, โปรดโพสต์ตัวอย่างใน ฟอรั่มสนับสนุน Aspose.PDF.

คำถามที่พบบ่อย

  1. FileSpecification.GetFileName เลือกชื่ออย่างไร?
    มันจะดึงชื่อจากชื่อ Unicode ของไฟล์ที่ฝังอยู่, ชื่อไฟล์ปกติ หรือคีย์ของคอลเลกชัน, whichever is available. หากไม่มีค่าใด ๆ ที่พร้อมใช้งาน, มันจะคืนค่าชื่อสำรองที่คุณส่งเข้าไป. เมธอดนี้ถูกเพิ่มใน Aspose.PDF for .NET 26.9.

  2. วิธีนี้ทำงานกับ PDF ที่ไม่ใช่พอร์ตโฟลิโอได้หรือไม่? ใช่, สำหรับไฟล์ที่แนบอยู่ระดับเอกสาร ไฟล์ที่แนบอยู่ในหน้าที่เฉพาะผ่านการระบุไฟล์แนบ (โดยปกติจะแสดงเป็นไอคอนคลิปหนีบกระดาษ) จะถูกจัดเก็บบนการระบุแทน ดังนั้นให้อ่านจาก FileAttachmentAnnotation.File ตามที่แสดงใน Extract files attached to pages.

  3. ทำไมต้องห่อผลลัพธ์ของ GetFileName ด้วย Path.GetFileName? ชื่อที่เก็บไว้ใน PDF ถูกตั้งโดยผู้สร้างไฟล์และอาจรวมส่วนของโฟลเดอร์ด้วย Path.GetFileName จะเก็บเฉพาะชื่อไฟล์เท่านั้น ดังนั้นไฟล์แนบทุกไฟล์จะถูกเขียนลงในโฟลเดอร์ผลลัพธ์ของคุณ

  4. อะไรจะเกิดขึ้นหากไฟล์แนบสองไฟล์มีชื่อเดียวกัน?
    ด้วย FileMode.Create ไฟล์ที่สองจะเขียนทับไฟล์แรก ตรวจสอบว่าพาธมีอยู่แล้วหรือไม่และเพิ่มเลขลำดับต่อท้าย ตามที่แสดงใน Handle duplicate and unsafe names.

  5. ฉันสามารถประมวลผลไฟล์แนบโดยไม่ต้องบันทึกลงดิสก์ได้หรือไม่? ใช่. คุณสมบัติ Contents เป็น Stream ดังนั้นคุณสามารถคัดลอกไปยัง MemoryStream อัปโหลดมัน หรือส่งต่อให้ไลบรารีอื่นแทนการเขียนลง FileStream.