Посібник з PDFsharp: Створення PDF-файлів за допомогою MigraDoc та PdfSharpCore

Посібник з PDFsharp: Створення PDF-файлів за допомогою MigraDoc та PdfSharpCore

PDFsharp — це бібліотека .NET з відкритим кодом для створення та редагування PDF-документів з коду C#. Ви малюєте текст, лінії та зображення на сторінці, викликаєте функцію «Зберегти» — і у вас є PDF-файл. Жодного браузерного движка, жодного власного бінарного файлу. Проєкт існував ще у 2005 році, і багато рахунків-фактур, звітів та сертифікатів, що виходять із серверних частин .NET, досі проходять через нього.

Я написав це для розробників, яким потрібні PDF-файли на сервері та які хочуть знати, на що вони йдуть. Ми розглянемо, як PDFsharp та MigraDoc поєднуються, яку збірку встановлювати, перший робочий файл, проблеми зі шрифтами в Linux, нещодавню зміну ліцензії та момент, коли варто обрати щось інше.

Що таке PDFsharp і що він може робити?

За бібліотекою PDFsharp стоїть empira Software GmbH, невелика німецька майстерня, яка підтримує цю справу вже майже двадцять років. Більшість вашого часу витрачається на один клас – XGraphics. Якщо ви коли-небудь малювали у WinForms за допомогою System.Drawing.Graphics, ви почуватиметеся як вдома вже за десять хвилин: шрифт, пензель, x та y, починайте.

З коробки ви отримуєте:

  • Створення PDF-документів з нуля з текстом, векторними фігурами, лініями та зображеннями
  • Відкривайте існуючі PDF-файли та додавайте до їхніх сторінок вміст, такий як штампи, водяні знаки або номери сторінок
  • Об'єднання та розділення документів шляхом імпорту сторінок з одного файлу в інший
  • Вбудовувати та створювати підмножини шрифтів , щоб файл виглядав однаково на кожному комп'ютері
  • Додайте закладки, посилання та метадані документа, такі як назва, автор і ключові слова
  • Захист файлів за допомогою паролів та прапорців дозволів
  • Підписуйте документи цифровим способом (починаючи з версії 6.2)

Розгортання нудне, я маю на увазі як похвалу. Все робиться на керованому коді, тому вашому операційному менеджеру ніколи не доведеться ставити Chrome без графічного інтерфейсу на систему чи шукати DLL-бібліотеку Ghostscript о 2-й годині ночі. Ви посилаєтеся на один пакет NuGet, надсилаєте — і все.

А тепер у чому загвоздка. Ви отримуєте полотно і нічого більше. Довгий абзац торкається нижнього поля? Ваша проблема. Таблиця виходить за межі першої сторінки? Теж ваша, якщо ви не застосуєте MigraDoc.

PDFsharp та MigraDoc: який шар вам потрібен?

Той самий постачальник, той самий графік випусків, зовсім різні завдання. MigraDoc Foundation знаходиться на один поверх вище від PDFsharp. Замість того, щоб вказувати йому, куди йде рядок, ви передаєте йому розділи, абзаци, таблиці, заголовки, нижні колонтитули, стилі та дивні діаграми, і він розбирається, куди все потрапляє. Виходить PDF. Або RTF, для колеги, який наполягає на відкритті всього у Word.

Моє скорочення: PDFsharp — це «розмістити цей текст за координатами x=40, y=120». MigraDoc — це «ось тридцять рядків і заголовок, який повторюється, ви сортуєте сторінки».

Завдання Найкраще підходить Чому
Односторінковий сертифікат або квиток із фіксованими позиціями PDFsharp Повний контроль над кожною координатою
Багатосторінковий звіт з таблицями та поточними заголовками МіграДок Автоматичне нумерування сторінок та стилі
Рахунок-фактура зі змінною кількістю позицій МіграДок Таблиці розширюються та розбиваються на сторінках
Штамп, водяний знак або номери сторінок на існуючому PDF-файлі PDFsharp MigraDoc створює лише нові документи
Об'єднання або розділення існуючих файлів PDFsharp Імпорт сторінок – це функція PDFsharp
Бізнес-діаграма у звіті МіграДок Вбудована підтримка діаграм
Змішаний: згенерований звіт плюс намальована на замовлення обкладинка Обидва MigraDoc може відображати на сторінці PDFsharp

Реальні проекти, як правило, мають і те, й інше. Основний текст через MigraDoc, намальована від руки обкладинка або штамп на PDF-файлі якогось постачальника через нижній шар. У будь-якому разі неможливо уникнути встановлення PDFsharp, оскільки пакет MigraDoc перетягує його як залежність.

Пояснення збірок PDFsharp: збірка Core, GDI+ та WPF

Новачки зазвичай опиняються наступними у списку пакетів NuGet. PDFsharp 6 постачається у трьох збірках, кожна з яких має власний двійник MigraDoc.

Пакет NuGet Збірка Платформи Шрифти та зображення
PDFsharp / PDFsharp-MigraDoc Ядро Windows, Linux, macOS Потрібен засіб розпізнавання шрифтів; зображення BMP, PNG, JPEG
PDFsharp-GDI / PDFsharp-MigraDoc-GDI GDI+ Тільки для Windows Використовує встановлені шрифти через System.Drawing
PDFsharp-WPF / PDFsharp-MigraDoc-WPF WPF Тільки для Windows Використовує встановлені шрифти через WPF

Поточні пакети орієнтовані на .NET 8, 9 та 10, а також .NET Standard 2.0 та .NET Framework 4.6.2. Тож охоплено практично все, над чим ще ведеться робота, від старого інструменту WinForms до абсолютно нового API ASP.NET Core.

Консольний додаток, веб-API, Docker, Azure Functions, щось на Linux? Збірка Core. GDI+ або WPF мають сенс лише для настільних додатків Windows, де потрібні системні шрифти або попередній перегляд у нативному елементі керування. Хтось на Stack Overflow якось запитав, чи потрібна їхньому консольному додатку версія WPF. Ні.

Посібник з PDFsharp

Як встановити PDFsharp з NuGet у Visual Studio

Ви все ще знайдете повідомлення на форумах часів WinForms, де вам радять взяти ZIP-архів, знайти DLL-файл і самостійно додати посилання. Ігноруйте їх. Встановіть PDFsharp через NuGet; менеджер пакетів відстежує версії, тому вам не доведеться цього робити.

  1. Відкрийте своє рішення у Visual Studio та клацніть правою кнопкою миші на проекті в Solution Explorer.
  2. Виберіть «Керування пакетами NuGet» , перейдіть на вкладку «Огляд» і знайдіть «PDFsharp».
  3. Виберіть PDFsharp (базова збірка) або PDFsharp-MigraDoc, якщо вам також потрібна верстка документа. Перевірте, чи видавець — empira Software GmbH.
  4. Натисніть кнопку «Встановити» та прийміть умови ліцензії.
  5. Зберіть проєкт один раз, щоб підтвердити правильність відновлення пакета.

Користувачі терміналів можуть пропустити клацання:

bash dotnet додати пакет PDFsharp dotnet додати пакет PDFsharp-MigraDoc

У консолі менеджера пакетів те саме — Install-Package PDFsharp. І, будь ласка, не змішуйте збірки. Я бачив, як команда втратила цілий день через конфлікти типів, тому що один проект посилався на PDFsharp, а його сусід запитував PDFsharp-GDI.

Ваш перший PDF-документ з PDFsharp на C

Нижче наведено інформацію про найменшу програму, яка створює односторінковий PDF-файл. Вона працює на збірці Core на будь-якій ОС, якщо налаштовано засіб розпізнавання шрифтів (наступний розділ).

```csharp
використання PdfSharp.Drawing;
використання PdfSharp.Pdf;

// PDFsharp 6.5+ вимагає вибору ліцензії перед першим використанням
PdfSharpLicense.SetAgplLicense();

var документ = новий PdfДокумент();
document.Info.Title = "Привіт, PDFsharp";

Сторінка PdfPage = документ.ДодатиСторінку();
XGraphics gfx = XGraphics.FromPdfPage(сторінка);

var шрифт = новий XFont("Arial", 20, XFontStyleEx.Bold);
gfx.DrawString("Привіт, PDFsharp!", шрифт, XBrushes.Black,
новий XRect(0, 0, сторінка.Ширина.Точка, сторінка.Висота.Точка),
XStringFormats.Center);

документ.Зберегти("привіт.pdf");
```

Кожна програма PDFsharp має таку форму: document, page, XGraphics, draw, save. Одиницями вимірювання є пункти (1/72 дюйма), а початок координат знаходиться у верхньому лівому куті. У версії 6.2.x видаліть лінію ліцензії. Цей API з'явився лише у версії 6.5.0.

А також версія MigraDoc:

```csharp
використання MigraDoc.DocumentObjectModel;
використання MigraDoc.Rendering;

var doc = новий Документ();
Розділ section = doc.ДодатиРозділ();
section.AddParagraph("Привіт, MigraDoc!");

var renderer = new PdfDocumentRenderer { Document = doc };
рендерер.RenderDocument();
renderer.PdfDocument.Save("hello-migradoc.pdf");
```

Жодних координат ніде. Додайте 500 абзаців і отримаєте скільки завгодно сторінок, без жодного коду для нульової сторінкової нумерації.

Шрифти в основній збірці PDFsharp: проблема з Resolver

Розпитайте навколо, і найчастіше ви почуєте скарги на шрифти. Збірки GDI+ та WPF просто зчитують встановлені шрифти TrueType з Windows. Збірка Core не може нічого припустити, оскільки тонкий контейнер Linux часто взагалі не має жодних корисних шрифтів. Тому перше розгортання Docker зазвичай завершується винятком про те, що не знайдено відповідного шрифту.

Виправлення полягає в розпізнаванні шрифтів, класі, який реалізує IFontResolver. Він має два методи:

  • ResolveTypeface зіставляє запитувану родину та стиль (наприклад, "Arial", жирний шрифт) з назвою обличчя
  • GetFont повертає необроблені байти TTF-файлу для цього імені обличчя

Зареєструйте його один раз під час запуску через GlobalFontSettings.FontResolver, перед створенням першого XFont.

```csharp
публічний клас AppFontResolver : IFontResolver
{
public FontResolverInfo? ResolveTypeface(string family, bool bold, bool italic)
=> new FontResolverInfo(bold ? "Inter-Bold" : "Inter-Regular");

public byte[]? GetFont(string faceName) => File.ReadAllBytes(Path.Combine(AppContext.BaseDirectory, "Fonts", faceName + ".ttf"));

}

GlobalFontSettings.FontResolver = новий AppFontResolver();
```

Речі, які варто знати, перш ніж вдарити їх самостійно:

  • Зберігайте файли TTF у папці Fonts у проєкті та налаштуйте їх копіювання до вихідного каталогу або вбудовуйте їх як ресурси, щоб образ контейнера завжди містив їх.
  • У випуску 6.2.0 було видалено старий CoreBuildFontResolver. У Windows або WSL2 ви можете відновити подібну поведінку за допомогою GlobalFontSettings.UseWindowsFontsUnderWindows, але це нічого не дає в Linux або macOS.
  • Офіційний репозиторій зразків містить SubstitutingFontResolver, який ви можете скопіювати як відправну точку.
  • Перевірте ліцензію шрифту, перш ніж вбудовувати комерційний шрифт у згенеровані файли. Відкрийте шрифти, такі як Inter, Roboto або Noto, щоб повністю уникнути цього питання.

З налаштованим резольвером вивід виглядає однаково у Windows, Linux та macOS.

Об'єднання, підписання та захист файлів за допомогою PDFsharp 6

Багато команд ніколи не створюють документ з нуля. Вони використовують бібліотеку для склеювання, штампування або блокування файлів, які вже існують. Об'єднання виконується в кілька рядків: відкрийте кожне джерело в режимі імпорту та скопіюйте сторінки.

csharp var output = new PdfDocument(); foreach (var path in new[] { "part1.pdf", "part2.pdf" }) { using var input = PdfReader.Open(path, PdfDocumentOpenMode.Import); foreach (PdfPage p in input.Pages) output.AddPage(p); } output.Save("merged.pdf");

Розділення — це той самий цикл у зворотному напрямку, один вихідний файл на сторінку або діапазон. Для захисту document.SecuritySettings приймає пароль користувача, пароль власника та прапорці дозволів (друк, копіювання тексту тощо).

Дві давно очікувані функції нарешті з'явилися у версії 6.2:

  • Цифрові підписи на основі CMS. Підписувач за замовчуванням постачається в окремій збірці PDFsharp.Cryptography, і ви можете підключити свій власний, реалізувавши IDigitalSigner. Підтримка сервера позначок часу працює на сучасній .NET, але не на збірці .NET Framework.
  • Вивід PDF/A для архівування. В офіційній документації його описують як робочий «з деякими обмеженнями» та все ще в розробці, тому перевірте результат за допомогою програми перевірки PDF/A, перш ніж покладатися на нього на відповідність.

У цьому випуску також з'явилися кольорові гліфи емодзі та керована реалізація MD5, що має значення, незалежно від того, чи працюєте ви за правилами FIPS, чи в Blazor.

Репозиторій PDFsharp, форки PdfSharpCore та версії 1.x

Пошукайте PDFsharp на GitHub, і ви знайдете кілька проектів майже з однаковою назвою. Звинувачуйте історію.

Стара лінійка 1.x (1.50, 1.51) працювала лише на .NET Framework. Коли вийшов .NET Core, людям не хотілося чекати, тому вони портували його самі. PdfSharpCore, започаткований Стефаном Штайгером і підхоплений пізніше іншими розробниками, — це той, який знає більшість людей. Він вирвав GDI+ і запустив код на Linux за роки до офіційного релізу.

Потім з'явився PDFsharp 6: належним чином переписаний на сучасному .NET з офіційною кросплатформною збіркою Core. Форки втратили більшу частину свого сенсу існування.

Демонструвати Супровідник Платформи Статус
PDFsharp 6.x (репозиторій empira/PDFsharp) empira Software GmbH .NET 8–10, .NET Standard 2.0, .NET Framework 4.6.2 Активно підтримується
PDFsharp 1.5x empira Software GmbH Тільки .NET Framework Вихідний код зберігається на GitHub, більше не підтримується
PdfSharpCore та його форки Громада .NET Core / .NET Standard 2.0 Залежить від форку, оновлення повільніші
PDFsharp-MigraDoc 6.x empira Software GmbH Те саме, що й PDFsharp 6 Активно підтримується

Отже, тема "PdfSharp проти PdfSharpCore", яка постійно з'являється на Reddit? Новий проект, офіційні пакети. Залишайте форк лише тоді, коли старий код вже спирається на нього, і міграція зараз не варта зусиль. А коли документації здається обмаль, перейдіть до окремого репозиторію зразків empira. Його папки та файли є запускаємими прикладами, що виключає будь-які здогадки.

Чи є PDFsharp безкоштовним? Зміни ліцензування в PDFsharp 6.5

Протягом більшої частини свого існування – так. Він мав ліцензію MIT, що означає комерційне використання майже без жодних зобов'язань. Кожен реліз до версії 6.2.4 включно досі має таку ліцензію.

Версія 6.5.0 це змінила. Бібліотека тепер має подвійну ліцензію:

  • AGPL (безкоштовно). Ви вмикаєте його, викликавши PdfSharpLicense.SetAgplLicense() перед використанням бібліотеки. AGPL вимагає, щоб ви зробили свій вихідний код доступним для користувачів, включаючи тих, хто взаємодіє з вашим програмним забезпеченням через мережу, тому він погано підходить для SaaS із закритим вихідним кодом.
  • Комерційна ліцензія. Ви купуєте ліцензійний ключ у постачальника та завантажуєте його за допомогою PdfSharpLicense.LoadLicense(...). Це знімає зобов'язання AGPL.

Починаючи з версії 6.5.0, ваш код має вибирати один варіант явно. Попередні версії 7.0 працюють так само.

На практиці:

  • Проєкти з відкритим кодом, сумісні з AGPL, можуть продовжувати використовувати найновішу версію безкоштовно.
  • Продукти із закритим кодом можна або придбати комерційну ліцензію, або залишитися на версії 6.2.x, яка залишається під егідою MIT. Залишитися на ній означає пропустити майбутні виправлення, тому чесно зважте цю вартість.
  • Що б ви не обрали, прочитайте фактичний текст ліцензії та попросіть свою команду юристів підписати його. Цей посібник не є юридичною консультацією.

Посібник з PDFsharp

Де PDFsharp не дотягує і з чим його поєднувати

Бібліотека добре виконує свою роботу. Просто завдання вузьке, і ті самі прогалини виникають у кожній темі форуму.

  • Немає можливості конвертувати HTML у PDF. PDFsharp не рендерить HTML або CSS. Існує доповнення спільноти HtmlRenderer.PdfSharp, але воно підтримує лише HTML 4.01 та CSS рівня 2, тому сучасні макети з flexbox або сіткою не виживуть. Команди, яким потрібні шаблони HTML, зазвичай використовують рендерер без headless-браузера.
  • Без JavaScript. Діаграми або контент, створений на стороні клієнта, не можуть бути захоплені.
  • Без рендерингу зображень. PDFsharp не може перетворити сторінку PDF на PNG для мініатюр або попереднього перегляду. Для цього потрібен окремий растеризатор.
  • Обмежене видобування тексту. Ви можете пройтися потоком контенту, але немає високорівневого API, який би повертав чистий текст з позиціями. PdfPig, окрема бібліотека з відкритим кодом, створена спеціально для читання та видобування тексту.
  • Часткова підтримка форм. Просте заповнення AcroForm працює; складні форми зі скриптами – це вже інша історія.
  • Для таблиць потрібен MigraDoc. Звичайний PDFsharp дозволяє самостійно розраховувати висоту кожного рядка.

Це не робить його поганим вибором. Документи на основі даних, такі як рахунки-фактури, виписки, етикетки та сертифікати, – це саме те, що йому потрібно, а розмір – мінімальний. Ідеальні до пікселів копії веб-сторінок – ні.

PDFsharp для криптовалютних рахунків-фактур та квитанцій про оплату

Квитанції, мабуть, найчастіше створюються за допомогою PDFsharp. З криптовалютними квитанціями трохи складніше, ніж з картковими. Гарна новина: щойно шлюз потрапляє на ваш вебхук (HTTP-зворотний виклик, що надсилається, коли статус платежу змінюється), ви отримуєте всі дані. Нічого зайвого для пошуку.

Що б я на один поставив:

  • Ідентифікатор замовлення або рахунку-фактури та реквізити продавця
  • Сума в криптовалюті та її фіатний еквівалент на момент оплати
  • Монета та мережа (наприклад, USDT на TRON проти USDT на Ethereum)
  • Хеш транзакції, щоб клієнт міг перевірити її в оглядачі блоків
  • Скорочена адреса гаманця-отримувача та час підтвердження
  • QR-код, що посилається на сторінку транзакції або рахунку-фактури

Моноширинний шрифт для хешів та адрес. Клієнти мружаться, дивлячись на них по одному символу за раз, а в Arial нуль і велика літера О виглядають як близнюки. Якщо хеш занадто широкий, перенесіть його; текст розміром 6 пунктів нікому не допоможе. Вбудуйте шрифти, збережіть файл із замовленням і підпишіть його, якщо ваш бухгалтер коли-небудь попросить квитанції.

Нічого з цього не стосується фактичного отримання грошей. Для цього вам потрібно підключити шлюз, такий як Plisio . Він приймає BTC, USDT та багато інших монет, створює рахунок-фактуру та викликає вашу кінцеву точку щоразу, коли статус змінюється. Ваш обробник передає корисне навантаження до MigraDoc, і покупець отримує квитанцію з вашим логотипом, поки він ще на сторінці подяки.

Висновок

Я постійно повертаюся до PDFsharp з однієї причини: він маленький і не заважає. Збірка Core працює будь-де, де працює .NET, а MigraDoc бере на себе роботу з макетуванням, коли одного полотна недостатньо. Три речі, які потрібно вирішити заздалегідь: яка збірка, як завантажуються шрифти та яка у вас ліцензія тепер, коли версія 6.5 перейшла на AGPL. Друкуйте дані, а не веб-сторінки, і вони прослужать роками.

Які-небудь питання?

Здебільшого, створення PDF-файлів з коду .NET. Уявіть собі рахунки-фактури, звіти, транспортні етикетки, сертифікати. Це також зручно для об’єднання та розділення, або додавання номерів сторінок та водяних знаків до PDF-файлів, створених кимось іншим. З MigraDoc поверх них, довгі документи з таблицями та діаграмами також не є проблемою.

До версії 6.2.4 так, це MIT, і ви можете постачати його в платних продуктах. Починаючи з версії 6.5.0, є розгалуження. Варіант AGPL нічого не коштує, але змушує вас ділитися своїм вихідним кодом; комерційний варіант коштує грошей, але не вимагає. Ваш стартовий код має вказувати, який саме.

Ні. Всередині немає движка HTML або CSS. Надбудова спільноти під назвою HtmlRenderer.PdfSharp намагається це зробити, але зупиняється на HTML 4.01 та CSS 2, тому все, що побудовано за допомогою flexbox або grid, руйнується. Для реальних веб-сторінок люди використовують конвертер, побудований на браузері без графічного інтерфейсу.

Через NuGet. Клацніть правою кнопкою миші на проекті у Visual Studio, виберіть «Керування пакетами NuGet», знайдіть «PDFsharp». У терміналі dotnet add package PDFsharp робить це. Потрібні також таблиці та пагінація? Додайте PDFsharp-MigraDoc. Відмовтеся від старого трюку копіювання DLL вручну.

Виправлені макети та редагування існуючих файлів: PDFsharp. Будь-що, де текст плавно перетікає, таблиці збільшуються, а сторінки розбиваються самостійно: MigraDoc. Чесно кажучи, ви, ймовірно, зрештою оберете обидва, і оскільки MigraDoc працює поверх PDFsharp, вони чудово працюють.

PDFsharp 6 орієнтований на .NET 8, 9 та 10, а також .NET Standard 2.0 та .NET Framework 4.6.2. Збірка Core працює на Windows, Linux та macOS. Збірки GDI+ та WPF доступні лише для Windows. Переходите на Linux? Спочатку налаштуйте засіб розпізнавання шрифтів, інакше ви зіткнетеся з помилками шрифтів.

Ready to Get Started?

Create an account and start accepting payments – no contracts or KYC required. Or, contact us to design a custom package for your business.

Make first step

Always know what you pay

Integrated per-transaction pricing with no hidden fees

Start your integration

Set up Plisio swiftly in just 10 minutes.