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
- โครงการ .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 ส่งคืน 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.Createsilently overwrites the first one. This also happens when several attachments have no name and all fall back toattachment.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.GetFileNamewith 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.
คำถามที่พบบ่อย
FileSpecification.GetFileName เลือกชื่ออย่างไร?
มันจะดึงชื่อจากชื่อ Unicode ของไฟล์ที่ฝังอยู่, ชื่อไฟล์ปกติ หรือคีย์ของคอลเลกชัน, whichever is available. หากไม่มีค่าใด ๆ ที่พร้อมใช้งาน, มันจะคืนค่าชื่อสำรองที่คุณส่งเข้าไป. เมธอดนี้ถูกเพิ่มใน Aspose.PDF for .NET 26.9.วิธีนี้ทำงานกับ PDF ที่ไม่ใช่พอร์ตโฟลิโอได้หรือไม่? ใช่, สำหรับไฟล์ที่แนบอยู่ระดับเอกสาร ไฟล์ที่แนบอยู่ในหน้าที่เฉพาะผ่านการระบุไฟล์แนบ (โดยปกติจะแสดงเป็นไอคอนคลิปหนีบกระดาษ) จะถูกจัดเก็บบนการระบุแทน ดังนั้นให้อ่านจาก
FileAttachmentAnnotation.Fileตามที่แสดงใน Extract files attached to pages.ทำไมต้องห่อผลลัพธ์ของ GetFileName ด้วย Path.GetFileName? ชื่อที่เก็บไว้ใน PDF ถูกตั้งโดยผู้สร้างไฟล์และอาจรวมส่วนของโฟลเดอร์ด้วย
Path.GetFileNameจะเก็บเฉพาะชื่อไฟล์เท่านั้น ดังนั้นไฟล์แนบทุกไฟล์จะถูกเขียนลงในโฟลเดอร์ผลลัพธ์ของคุณอะไรจะเกิดขึ้นหากไฟล์แนบสองไฟล์มีชื่อเดียวกัน?
ด้วยFileMode.Createไฟล์ที่สองจะเขียนทับไฟล์แรก ตรวจสอบว่าพาธมีอยู่แล้วหรือไม่และเพิ่มเลขลำดับต่อท้าย ตามที่แสดงใน Handle duplicate and unsafe names.ฉันสามารถประมวลผลไฟล์แนบโดยไม่ต้องบันทึกลงดิสก์ได้หรือไม่? ใช่. คุณสมบัติ
Contentsเป็นStreamดังนั้นคุณสามารถคัดลอกไปยังMemoryStreamอัปโหลดมัน หรือส่งต่อให้ไลบรารีอื่นแทนการเขียนลงFileStream.
