Эта страница может содержать автоматически переведенный текст.

Преобразование HTML в PDF в C# и VB.NET

Если вы уже вложили значительное время и средства в создание контента в HTML-форме, вам может потребоваться создавать PDF из этого HTML. Такой подход — естественный выбор для тех, кто хочет избежать дублирования работы.

Эта статья — подробное руководство по преобразованию HTML в PDF в .NET с использованием Docotic.Pdf вместе с его бесплатным дополнением HtmlToPdf.

Сведения о том, почему Docotic.Pdf — правильный выбор, как установить дополнение и как работает преобразование внутри, см. на странице обзора API HTML в PDF.

Преобразование HTML в PDF

Простое преобразование HTML в PDF на C#

Сначала установите дополнение.

Install-Package BitMiracle.Docotic.Pdf.HtmlToPdf

Используя API HTML в PDF, код преобразования на C# может выглядеть так:

static async Task ConvertUrlToPdfAsync(string urlString, string pdfFileName)
{
    using var converter = await HtmlConverter.CreateAsync();
    using var pdf = await converter.CreatePdfAsync(new Uri(urlString));
    pdf.Save(pdfFileName);
}

Это довольно просто. Для создания PDF-документа требуется всего два вызова.

Код создает экземпляр конвертера и использует его для генерации PDF из HTML. Вы можете редактировать PDF или подписать его цифровой подписью. Для простоты пример кода сохраняет документ без изменений.

Как видите, API асинхронный и вообще не предоставляет синхронных методов.

Использование асинхронного API в синхронном коде

Бывают случаи, когда нужно вызывать API из синхронного кода. Например, если ваше консольное приложение использует более старую версию C# и у вас нет async Main. Не беспокойтесь, вы все равно можете использовать дополнение в своем приложении.

Следующий код показывает, как преобразовать URL в PDF в обычном синхронном методе:

Task.Run(async () =>
{
    using var converter = await HtmlConverter.CreateAsync();
    var uri = new Uri("https://bitmiracle.com/pdf-library/html-pdf/");
    using var pdf = await converter.CreatePdfAsync(uri);
    pdf.Save("output.pdf");
}).GetAwaiter().GetResult();

Приложения VB.NET используют похожий код. Ниже приведен фрагмент, который показывает, как преобразовать HTML в PDF в синхронном коде VB.NET.

Task.Run(
    Async Function()
        Using converter = Await HtmlConverter.CreateAsync()
            Dim uri = New Uri("https://bitmiracle.com/pdf-library/html-pdf/")
            Using pdf = Await converter.CreatePdfAsync(uri)
                pdf.Save("output.pdf")
            End Using
        End Using
    End Function
).GetAwaiter().GetResult()

Обратите внимание: в общем случае не рекомендуется вызывать async-методы синхронно, поэтому используйте обертку только если нет другого выбора.

Пример кода

Мы предоставляем примеры кода для консольных приложений, Windows Forms и WPF. Скачайте полные тестовые проекты из нашего репозитория GitHub:

Также есть группа примеров HTML в PDF. Каждый пример доступен в версиях для C# и VB.NET.

Создание PDF из HTML-строки или файла в C# и VB.NET

Преобразовать HTML-строку в PDF с помощью API очень просто. Строка может содержать полный HTML-документ или только фрагмент. Конвертер создаст для вас PDF из HTML-кода.

using var converter = await HtmlConverter.CreateAsync();

var html = "<body><br><br><br><h1>Hello, World</h1></body>";
using var pdf = await converter.CreatePdfFromStringAsync(html);
pdf.Save("output.pdf");

HTML может содержать относительные ссылки на изображения, скрипты и CSS-файлы. Чтобы корректно преобразовать такой код, нужно указать базовый URL для всех относительных ссылок в HTML. Вот как задать базовый URL с помощью параметров преобразования:

using var converter = await HtmlConverter.CreateAsync();

var incompleteHtml = "<img src=\"/images/team.svg\"></img>";

var options = new HtmlConversionOptions();
options.Load.BaseUri = new Uri("https://bitmiracle.com/");

using var pdf = await converter.CreatePdfFromStringAsync(incompleteHtml, options);
pdf.Save("output.pdf");

В нашем репозитории GitHub есть полный тестовый проект.

Преобразование HTML-файла почти не отличается от преобразования URL. Просто используйте перегрузку CreatePdfAsync, которая принимает путь вместо URL. Базовый URL и другие параметры также поддерживаются при преобразовании HTML-файла в PDF в коде C# или VB.NET.

var sampleHtmlPath = @"C:\path\to\sample.html";
using var pdf = await converter.CreatePdfAsync(sampleHtmlPath);
pdf.Save("output.pdf");

Вы также можете конвертировать SVG-изображения в PDF с помощью API.

Использование настраиваемого размера страницы, полей и масштаба

При работе с веб-страницами, имеющими широкую компоновку, можно либо увеличить размер выходного PDF, либо уменьшить масштаб содержимого, чтобы оно помещалось на странице PDF. Для лучшего позиционирования уменьшенного содержимого можно также задать поля.

Хорошо масштабированный PDF обеспечивает более удобное чтение, поскольку читателю не нужно приближать или отдалять изображение, чтобы просматривать содержимое корректно. Если HTML-документ трудно читать из-за маленького размера шрифта, можно увеличить масштаб содержимого.

По умолчанию API создает PDF с размером страницы A4. Поля и масштаб по умолчанию отсутствуют. С помощью параметров преобразования можно изменить эти настройки.

См. как задать коэффициент масштабирования и поля при генерации PDF из HTML

using var converter = await HtmlConverter.CreateAsync();

var html = "<html><head><style>body { background-color: coral; margin-top: 100px;}</style></head>" +
"<body><h1>Did you notice the margins and the scale?</h1></body></html>";

var options = new HtmlConversionOptions();
options.Page.MarginLeft = 10;
options.Page.MarginTop = 20;
options.Page.MarginRight = 30;
options.Page.MarginBottom = 40;
options.Page.Scale = 1.5;

using var pdf = await converter.CreatePdfFromStringAsync(html, options);
pdf.Save("output.pdf");

Репозиторий примеров Docotic.Pdf содержит полный проект.

API HTML в PDF может добавлять повторяемые блоки нижнего / верхнего колонтитула на сгенерированные страницы. Конвертер создает эти блоки из HTML-шаблонов, указанных в параметрах страницы. Мы рекомендуем использовать встроенные стили и Data URI для изображений внутри шаблонов.

Конвертер размещает верхние и нижние колонтитулы внутри полей страницы. Поскольку поля страницы по умолчанию небольшие, содержимое верхнего и нижнего колонтитула может быть не видно. Рекомендуем явно задавать верхнее и нижнее поля. Размер должен соответствовать размеру верхнего и нижнего колонтитула соответственно.

См. как изменить HTML в PDF и добавить верхний и нижний колонтитулы

using var converter = await HtmlConverter.CreateAsync();

var options = new HtmlConversionOptions();
options.Page.HeaderTemplate = File.ReadAllText("header-template.html");
options.Page.MarginTop = 50;

options.Page.FooterTemplate = File.ReadAllText("footer-template.html");
options.Page.MarginBottom = 50;

var url = new Uri("https://www.iana.org/numbers");
using var pdf = await converter.CreatePdfAsync(url, options);
pdf.Save("output.pdf");

Шаблоны используют обычный HTML-код с поддержкой нескольких переменных. Эти переменные: date, title, url, pageNumber и totalPages. И шаблоны верхнего колонтитула, и шаблоны нижнего колонтитула поддерживают один и тот же набор переменных.

Полный тестовый проект и код шаблонов находятся в репозитории примеров Docotic.Pdf. Пример кода показывает, как использовать переменные и Data URI в шаблонах.

Преобразование HTML в PDF на C# с защитой паролем

Некоторые веб-страницы требуют аутентификации для доступа к ним. Когда вы открываете защищенный URL, требующий HTTP-аутентификации, браузер запрашивает имя пользователя и пароль.

С помощью параметров преобразования можно указать API предоставлять учетные данные для веб-страниц, требующих входа в систему.

Этот код на C# показывает, как преобразовать HTML с защитой паролем в PDF

using var converter = await HtmlConverter.CreateAsync();
var url = new Uri("http://httpbin.org/basic-auth/foo/bar");

var options = new HtmlConversionOptions();
options.Authentication.SetCredentials("foo", "bar");

using var pdf = await converter.CreatePdfAsync(url, options);
pdf.Save("output.pdf");

Найдите полный рабочий пример в репозитории примеров.

Если странице для корректной работы нужны некоторые cookie, это тоже легко. Просто добавьте эти cookie в параметры. Вот как это сделать:

var options = new HtmlConversionOptions();
options.Cookies.Add(new Cookie("sessionID", "my-session-ID"));

using var pdf = await converter.CreatePdfAsync(url, options);
pdf.Save("output.pdf");

Отложенный запуск преобразования

По умолчанию преобразование начинается сразу после загрузки. Отложенное преобразование HTML в PDF может быть полезно, если после загрузки страница еще некоторое время обновляется. Это часто бывает при работе с динамическим содержимым, создаваемым JavaScript или вызовами AJAX.

Тест Acid 3 — хороший пример страницы, которой полезна задержка перед преобразованием. Тест выполняет ряд проверок, чтобы оценить способность браузера корректно отображать сложные веб-страницы. Эти проверки требуют времени. Попробуйте изменить время ожидания в следующем коде, чтобы увидеть, как это влияет на результаты преобразования.

var options = new HtmlConversionOptions();
options.Start.SetStartAfterDelay(10 * 1000);

using var converter = await HtmlConverter.CreateAsync();
var url = new Uri("http://acid3.acidtests.org/");
using var pdf = await converter.CreatePdfAsync(url, options);
pdf.Save("output.pdf");

Приведенный выше код показывает, как преобразовать HTML в PDF с задержкой. Хотя дополнительное время помогает получить лучшие результаты, учитывайте, что добавление задержек может повлиять на производительность. Недостаточная задержка может отрицательно сказаться на качестве преобразования. Альтернатива задержке — использовать скрипт, который будет выполняться, пока страница не будет готова.

Вы можете получить полный тестовый проект в репозитории примеров Docotic.Pdf.

Выполнение JavaScript перед преобразованием

Дополнение предоставляет способ запускать JS-код перед преобразованием. Код может динамически генерировать или изменять HTML-содержимое. Например, он может переключать элементы или инициировать загрузку динамического содержимого.

Следующий код показывает, как отложить преобразование HTML в PDF, пока JavaScript не завершит работу.

using var converter = await HtmlConverter.CreateAsync();

var options = new HtmlConversionOptions();
var js = @"document.body.style.backgroundColor = 'green';";
options.Start.SetStartAfterScriptRun(js);

var url = new Uri("https://google.com");
using var pdf = await converter.CreatePdfAsync(url, options);
pdf.Save("output.pdf");

Приведенный выше фрагмент использует очень простой код только для иллюстрации подхода. Для более реалистичного примера см. соответствующее sample-приложение в нашем репозитории GitHub. Приложение показывает, как работать со страницей, которая динамически загружает свое содержимое. Код JavaScript в приложении прокручивает страницу, пока не перестанет загружаться новый контент. После этого выполняется преобразование в PDF.

Преобразование HTML в PDF в .NET с игнорированием ошибок SSL

При отправке защищенных запросов для загрузки HTML дополнение проверяет, является ли SSL-сертификат, который подтверждает идентичность сайта и обеспечивает зашифрованное соединение, действительным и доверенным.

По умолчанию дополнение вызовет исключение, если конвертер HTML в PDF не доверяет сертификату по какой-либо причине. Обычно это происходит из-за самоподписанного, отозванного или просроченного сертификата.

Если вы понимаете риск принятия недоверенного сертификата, можно указать дополнению пропускать проверки с помощью параметров движка.

var engineOptions = new HtmlEngineOptions
{
    IgnoreSslErrors = true
};
using var converter = await HtmlConverter.CreateAsync(engineOptions);

var url = new Uri("https://self-signed.badssl.com/");
using var pdf = await converter.CreatePdfAsync(url);
pdf.Save("output.pdf");

За полным кодом переходите в репозиторий примеров Docotic.Pdf.

Наложение HTML поверх существующего PDF

Бывают случаи, когда нужно использовать существующий PDF в качестве фона для результата преобразования. Например, если у вас есть изображение формы и нужно разместить что-то поверх пустых областей на этом изображении. В результате получится вид заполненной формы. Это возможно с Docotic.Pdf и дополнением.

Этот процесс включает создание нового PDF из HTML (содержимого наложения), а затем его объединение с существующим PDF. В итоговом документе будут и исходное содержимое, и новое наложение. Вот код, который иллюстрирует этот процесс.

using var converter = await HtmlConverter.CreateAsync();

var options = new HtmlConversionOptions();
options.Page.SetSizeInches(4.13, 5.83);

string htmlCode =
    "<div style=\"position: absolute; top: 270px; right: 100px;\">" +
    "I would like to put this here</div>";
using var htmlPdf = await converter.CreatePdfFromStringAsync(htmlCode, options);

using var pdf = new PdfDocument("pdf-to-merge-with.pdf");
var xObj = pdf.CreateXObject(htmlPdf.Pages[0]);

pdf.Pages[0].Canvas.DrawXObject(xObj, 0, 0);
pdf.Save("output.pdf");

Важно указать размер страницы для наложения. Обычно размер должен быть равен размеру страницы, на которую вы хотите наложить содержимое. Затем нужно создать новый PDF с содержимым наложения. Обратите внимание: фон по умолчанию прозрачный. При необходимости вы можете изменить фон, запустив скрипт перед преобразованием.

Приведенный выше код:

  • создает PDF-документ с прозрачной страницей из HTML
  • открывает существующий PDF
  • создает XObject из первой страницы преобразованного документа в существующем документе
  • рисует XObject поверх первой PDF-страницы существующего документа

Полный тестовый проект с примером исходного PDF находится в репозитории примеров Docotic.Pdf.