קובץ PDF יכול לשאת קבצים אחרים בתוכו. זה יכול להיות תיק שמאגד חוזים וגיליונות אלקטרוניים, או דוח עם הנתונים המקוריים שלו מצורפים. כאשר אתה מחלץ את הקבצים האלה בקוד, אתה רוצה שכל אחד יישמר תחת השם שהמחבר שלו נתן, ולא attachment1.bin. מדריך זה מראה כיצד לחלץ קבצים משובצים מקובץ PDF עם שמות מקוריים ב‑C# באמצעות Aspose.PDF for .NET. תפתח קובץ PDF, תעבור על הקבצים המשובצים שבו, תחלץ את שם כל קובץ באמצעות FileSpecification.GetFileName, ותכתוב את התוכן לתיקייה.
היכן קובץ PDF מאחסן את שם הקובץ המוטמע
כל קובץ משובץ מתואר על ידי מפרט קובץ, ומפרט קובץ יכול לרשום את השם ביותר ממקום אחד. יש שם קובץ ב‑Unicode, שם קובץ סטנדרטי, והמפתח שבו הקובץ מופיע באוסף הקבצים המשובצים של המסמך. יצרני PDF אינם ממלאים זאת באופן עקבי, וחלקם משאירים את השם חסר לחלוטין.
Aspose.PDF for .NET מספקת את המאפיין FileSpecification.GetFileName כדי להתמודד עם זה. הוא פותר את השם משם ה‑Unicode, משם הקובץ הרגיל, או ממפתח האוסף, בהתאם למה שזמין, כך שאתה עדיין מקבל שם שמיש כאשר שם ה‑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
או עם ה-CLI של .NET:
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 אינו מספק שם. בחר fallback שהגיוני עבור היישום שלך.
הסר קטעי תיקייה. שם מאוחסן יכול לכלול נתיב כגון 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 בעולם האמיתי:
- שני קבצים מצורפים יכולים לשתף שם, ו‑
FileMode.Createמחליף בשקט את הראשון. זה קורה גם כאשר כמה קבצים מצורפים אינם בעלי שם וכולם נופלים ל‑attachment.bin. - שם שתקף במערכת הפעלה אחת יכול להכיל תווים שאינם תקפים במערכת אחרת, כגון
:ב‑Windows. - שם שמאוחסן שמסתיים במפריד נתיב משאיר את
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 מציגה את המאפיינים other name ו‑description שניתן לקרוא עבור כל קובץ משולב. אם קובץ PDF אינו מתבצע לחילוץ כצפוי, פרסמו דוגמה ב-פורום התמיכה של Aspose.PDF.
שאלות נפוצות
איך FileSpecification.GetFileName בוחר שם? הוא פותר את השם משם Unicode של הקובץ המוטמע, שם קובץ רגיל, או מפתח האוסף, בהתאם למה שזמין. אם אף אחד מהם אינו זמין, הוא מחזיר את שם ברירת המחדל שהוזן. השיטה נוספה ב‑Aspose.PDF for .NET 26.9.
האם זה עובד עבור קבצי PDF שאינם פורטפוליו? כן, עבור קבצים המצורפים ברמת המסמך. קבצים המצורפים לדף ספציפי דרך אנוטציית קובץ מצורף (בדרך כלל מוצגים כסמל של מהדק נייר) נשמרים על האנוטציה במקום, ולכן יש לקרוא אותם מ-
FileAttachmentAnnotation.File, כפי שמוצג ב-חילוץ קבצים מצורפים לדפים.למה לעטוף את תוצאת GetFileName ב‑Path.GetFileName?
השם השמור בקובץ PDF נקבע על ידי מי שיצר את הקובץ ויכול לכלול חלקי תיקייה.Path.GetFileNameמשאיר רק את שם הקובץ, ולכן כל קובץ מצורף נכתב בתוך תיקיית הפלט שלך.מה קורה אם לשתי קבצים מצורפים יש את אותו השם? עם
FileMode.Create, הקובץ השני מחליף את הראשון. בדוק אם הנתיב כבר קיים והוסף סיומת מספרית, כפי שמוצג ב-טפל בשם כפול ולא בטוח.האם אני יכול לעבד קובץ מצורף מבלי לשמור אותו על הדיסק? כן. המאפיין
ContentsהואStream, ולכן ניתן להעתיק אותו ל-MemoryStream, להעלות אותו, או להעביר אותו לספרייה אחרת במקום לכתוב אותו ל-FileStream.
