Esta página puede contener texto traducido automáticamente.

Convertir HTML a PDF en C# y VB.NET

Si ya ha invertido mucho tiempo y dinero en crear contenido en formato HTML, quizá quiera generar PDF a partir de ese HTML. Este enfoque es una opción natural para cualquiera que quiera evitar trabajo duplicado.

Este artículo es una guía detallada para convertir HTML a PDF en .NET usando Docotic.Pdf junto con su complemento gratuito HtmlToPdf.

Para obtener información sobre por qué Docotic.Pdf es la opción adecuada, cómo instalar el complemento y cómo funciona internamente la conversión, consulte la página Resumen de la API HTML a PDF.

Conversión de HTML a PDF

Conversión simple de HTML a PDF en C#

Primero, instale el complemento.

Install-Package BitMiracle.Docotic.Pdf.HtmlToPdf

Usando la API HTML a PDF, el código de conversión en C# puede verse así:

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);
}

Es bastante sencillo. Solo se requieren dos llamadas para generar un documento PDF.

El código crea una instancia del convertidor y la usa para generar un PDF a partir de HTML. Puede editar el PDF o firmarlo con una firma digital. Por simplicidad, el código de ejemplo guarda el documento tal cual.

Como puede ver, la API es asincrónica y no proporciona métodos sincrónicos en absoluto.

Uso de la API asincrónica en código sincrónico

Hay casos en los que necesita llamar a la API desde código sincrónico. Por ejemplo, cuando su aplicación de consola usa una versión anterior de C# y no dispone de async Main. No se preocupe, aún puede usar el complemento en su aplicación.

El siguiente código muestra cómo convertir una URL a PDF en un método sincrónico normal:

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();

Las aplicaciones VB.NET usan un código similar. Aquí hay un fragmento que muestra cómo convertir HTML a PDF en código VB.NET sincrónico.

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()

Tenga en cuenta que, en general, no se recomienda llamar métodos asíncronos de forma sincrónica, así que use el envoltorio solo cuando no tenga otra opción.

Código de ejemplo

Proporcionamos códigos de ejemplo para aplicaciones de consola, Windows Forms y WPF. Descargue los proyectos de prueba completos desde nuestro repositorio de GitHub:

También hay un grupo de ejemplos de HTML a PDF. Cada ejemplo está disponible en versiones de C# y VB.NET.

Crear un PDF con una cadena HTML o un archivo en C# y VB.NET

Es fácil convertir una cadena HTML a PDF con la API. La cadena puede contener un documento HTML completo o solo un fragmento. El convertidor creará un PDF a partir del código HTML por usted.

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 puede contener referencias relativas a imágenes, scripts y archivos CSS. Para convertir correctamente ese código, necesitaría especificar una URL base para todos los enlaces relativos en el HTML. Así se especifica una URL base usando las opciones de conversión:

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");

Nuestro repositorio de GitHub contiene el proyecto de prueba completo.

Convertir un archivo HTML es casi lo mismo que convertir una URL. Solo use la sobrecarga CreatePdfAsync que acepta una ruta en lugar de una URL. La URL base y otras opciones también se admiten al convertir un archivo HTML a PDF en código C# o VB.NET.

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

También puede convertir imágenes SVG a PDF usando la API.

Usar tamaño de página, márgenes y escala personalizados

Cuando trabaja con páginas web que tienen diseños anchos, puede aumentar el tamaño del PDF de salida o reducir la escala del contenido para que quepa en la página PDF. Para posicionar mejor el contenido escalado, también puede configurar márgenes.

Un PDF bien escalado ofrece una mejor experiencia de lectura, porque los lectores no necesitarán acercar ni alejar la vista para ver el contenido correctamente. Si el documento HTML es difícil de leer por un tamaño de fuente pequeño, puede aumentar la escala del contenido.

De forma predeterminada, la API genera PDF con tamaño de página A4. No hay márgenes ni ampliación. Usando las opciones de conversión, puede cambiar estos ajustes.

Vea cómo configurar el factor de escala y los márgenes al generar PDF a partir de 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");

El repositorio de muestras de Docotic.Pdf contiene el proyecto completo.

La API HTML a PDF puede agregar bloques repetibles de pie de página / encabezado en las páginas generadas. El convertidor crea los bloques a partir de las plantillas HTML especificadas en opciones de página. Recomendamos usar estilos en línea y URI de datos para las imágenes dentro de las plantillas.

El convertidor coloca los encabezados y pies de página dentro de los márgenes de la página. Dado que los márgenes predeterminados de la página son pequeños, el contenido del encabezado y el pie de página puede no ser visible. Recomendamos especificar explícitamente los márgenes superior e inferior. El tamaño debe coincidir, respectivamente, con el tamaño del encabezado y del pie de página.

Vea cómo cambiar HTML a PDF y agregar encabezado y pie de página

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");

Las plantillas usan código HTML normal con soporte para algunas variables. Estas variables son date, title, url, pageNumber y totalPages. Tanto las plantillas de encabezado como las plantillas de pie de página admiten el mismo conjunto de variables.

El proyecto de prueba completo y el código de plantilla están en el repositorio de muestras de Docotic.Pdf. El código de ejemplo muestra cómo usar las variables y los URI de datos en las plantillas.

Conversión de HTML a PDF en C# protegida con contraseña

Algunas páginas web requieren autenticación para acceder a ellas. Cuando accede a una URL segura que requiere autenticación HTTP, el navegador le pide que proporcione nombre de usuario y contraseña.

Usando las opciones de conversión, puede indicar a la API que proporcione credenciales para páginas web que requieren inicio de sesión.

Este código C# muestra cómo convertir HTML protegido con contraseña a 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");

Encuentre el ejemplo funcional completo en el repositorio de ejemplos.

También es fácil si la página necesita que se establezcan algunas cookies para funcionar correctamente. Solo agregue esas cookies a las opciones. Así se hace:

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");

Retrasar el inicio de la conversión

De forma predeterminada, la conversión comienza inmediatamente después de la carga. Retrasar la conversión de HTML a PDF puede ser útil si la página sigue actualizándose durante un tiempo después de cargarse. Suele ocurrir al tratar contenido dinámico generado por JavaScript o llamadas AJAX.

La prueba Acid 3 es un ejemplo perfecto de una página que se beneficiaría de un retraso antes de la conversión. La prueba ejecuta una serie de comprobaciones para evaluar la capacidad de un navegador para renderizar correctamente páginas web complejas. Estas comprobaciones requieren tiempo. Pruebe a cambiar el tiempo de espera en el código siguiente para ver cómo afecta a los resultados de la conversión.

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");

El código anterior muestra cómo convertir HTML a PDF con retraso. Aunque el tiempo adicional ayuda a obtener mejores resultados, tenga en cuenta que añadir retrasos puede afectar al rendimiento. Los retrasos insuficientes pueden afectar negativamente a la calidad de la conversión. Una alternativa a usar un retraso es usar un script que se ejecute hasta que la página esté lista.

Puede obtener el proyecto de prueba completo en el repositorio de muestras de Docotic.Pdf.

Ejecutar JavaScript antes de la conversión

La API del complemento proporciona una forma de ejecutar código JS antes de la conversión. El código puede generar o modificar dinámicamente el contenido HTML. Por ejemplo, puede alternar elementos o provocar la carga dinámica del contenido.

El siguiente código muestra cómo retrasar la conversión de HTML a PDF hasta que JavaScript haya terminado.

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");

El fragmento anterior usa un código muy simple solo para ilustrar el enfoque. Para un ejemplo más realista, consulte la aplicación de ejemplo correspondiente en nuestro repositorio de GitHub. La aplicación muestra cómo tratar una página que carga su contenido dinámicamente. El código JavaScript de la aplicación desplaza la página hasta que ya no hay más contenido nuevo. Después de eso, se realiza la conversión a PDF.

Convertir HTML a PDF en .NET ignorando errores de SSL

Al enviar solicitudes seguras para cargar HTML, el complemento comprueba si el certificado SSL que autentica la identidad de un sitio web y habilita una conexión cifrada es válido y confiable.

De forma predeterminada, el complemento lanzará una excepción si el convertidor de HTML a PDF no confía en el certificado por cualquier motivo. Suele ocurrir debido a un certificado autofirmado, revocado o caducado.

Si comprende el riesgo de aceptar un certificado no confiable, puede indicar al complemento que omita las comprobaciones usando las opciones del motor.

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");

Para el código completo, vaya al repositorio de muestras de Docotic.Pdf.

Superponer HTML sobre un PDF existente

Hay casos en los que querría usar un PDF existente como fondo para el resultado de la conversión. Por ejemplo, cuando tiene una imagen de un formulario y quiere poner algo sobre las áreas vacías de esa imagen. El resultado parecerá un formulario rellenado. Esto es posible con Docotic.Pdf y el complemento.

Este proceso consiste en crear un nuevo PDF a partir del HTML (el contenido superpuesto) y luego fusionarlo con el PDF existente. El documento final incluirá tanto el contenido original como la nueva superposición. Este es el código que ilustra el proceso.

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");

Es importante especificar un tamaño de página para la superposición. Normalmente, el tamaño debe ser igual al tamaño de la página que desea superponer. Luego necesitaría generar el nuevo PDF con el contenido superpuesto. Tenga en cuenta que, de forma predeterminada, el fondo es transparente. Si es necesario, puede cambiar el fondo ejecutando un script antes de la conversión.

El código anterior:

  • crea un documento PDF con una página transparente a partir del HTML
  • abre un PDF existente
  • crea un XObject a partir de la primera página del documento convertido en el documento existente
  • dibuja el XObject sobre la primera página PDF del documento existente

El proyecto de prueba completo con un PDF fuente de ejemplo está en el repositorio de muestras de Docotic.Pdf.