PDF може містити інші файли всередині себе. Він може бути портфоліо, яке об’єднує контракти та електронні таблиці, або звітом з прикріпленими вихідними даними. Коли ви витягуєте ці файли у коді, ви хочете, щоб кожен з них зберігався під ім’ям, яке йому надало автор, а не attachment1.bin. Цей підручник показує, як витягнути вбудовані файли з PDF з оригінальними іменами у C# за допомогою Aspose.PDF for .NET. Ви відкриєте PDF, пройдетеся по його вбудованих файлах, визначите ім’я кожного файлу за допомогою FileSpecification.GetFileName і запишете вміст у папку.

Де PDF зберігає назву вбудованого файлу

Кожен вбудований файл описується специфікацією файлу, і специфікація файлу може записувати ім’я в декількох місцях. Існує ім’я файлу Unicode, стандартне ім’я файлу та ключ, під яким файл зазначений у колекції вбудованих файлів документа. Виробники PDF не заповнюють ці дані послідовно, і деякі зовсім опускають ім’я.

Aspose.PDF for .NET надає властивість FileSpecification.GetFileName для вирішення цієї проблеми. Вона визначає ім’я з Unicode‑імені, звичайного імені файлу або ключа колекції, залежно від того, що доступно, тому ви все одно отримуєте придатне ім’я, коли Unicode‑ім’я відсутнє. Ви можете передати резервне ім’я для файлів, які взагалі не мають імені. Необов’язковий другий параметр визначає, чи дозволено порожнє ім’я, коли ім’я файлу недоступне. Ви отримуєте один виклик замість власної логіки читання PDF‑словників.

Примітка: Приклади в цій статті використовують лише аргумент резервного варіанту.

Document.EmbeddedFiles містить вкладення рівня документа, які включають файли у PDF‑портфоліо. Файли, прикріплені до конкретної сторінки за допомогою анотації прикріплення файлу (зазвичай показується як іконка скріпки), зберігаються в анотації; Extract files attached to pages охоплює їх.

Використання 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‑файлах:

  • Два вкладення можуть мати однакову назву, і 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 class reference перераховує інші властивості name та description, які можна прочитати з кожного вбудованого файлу. Якщо PDF не розпаковується як очікувалося, розмістіть приклад у Aspose.PDF форум підтримки.

FAQs

  1. Як FileSpecification.GetFileName обирає ім’я?
    Він визначає ім’я з Unicode‑імені вбудованого файлу, звичайного імені файлу або ключа колекції, залежно від того, що доступно. Якщо жодне з них недоступне, він повертає резервне ім’я, яке ви передаєте. Метод був доданий у 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 другий файл перезаписує перший. Перевірте, чи шлях вже існує, і додайте числовий суфікс, як показано в Обробка дублікатів та небезпечних імен.

  5. Чи можу я обробляти вкладення без збереження його на диск? Так. Властивість Contents є Stream, тому ви можете скопіювати її у MemoryStream, завантажити її або передати інший бібліотеці замість запису у FileStream.