Guía de PDFsharp: Crea archivos PDF con MigraDoc y PdfSharpCore

Guía de PDFsharp: Crea archivos PDF con MigraDoc y PdfSharpCore

PDFsharp es una biblioteca .NET de código abierto para crear y editar documentos PDF desde código C#. Simplemente dibujas texto, líneas e imágenes en una página, llamas a Guardar y listo, tienes un archivo PDF. No requiere motor de navegador ni binario nativo. El proyecto data de 2005, y muchas de las facturas, informes y certificados generados por sistemas .NET aún se procesan con esta biblioteca.

Escribí esto para desarrolladores que necesitan archivos PDF en el servidor y quieren saber qué esperar. Hablaremos sobre cómo se integran PDFsharp y MigraDoc, qué versión instalar, un primer archivo funcional, los problemas con las fuentes en Linux, el reciente cambio de licencia y el momento en que conviene elegir otra alternativa.

¿Qué es PDFsharp y qué puede hacer?

Detrás de la biblioteca PDFsharp se encuentra empira Software GmbH, una pequeña empresa alemana que la ha mantenido viva durante casi veinte años. La mayor parte del tiempo se dedica a una sola clase: XGraphics. Si alguna vez has trabajado con gráficos en WinForms usando System.Drawing.Graphics, te sentirás como en casa en diez minutos: fuente, pincel, coordenadas x e y, ¡listo!

De fábrica obtienes:

  • Crea documentos PDF desde cero con texto, formas vectoriales, líneas e imágenes.
  • Abra archivos PDF existentes y agregue contenido a sus páginas, como sellos, marcas de agua o números de página.
  • Combinar y dividir documentos importando páginas de un archivo a otro.
  • Incrusta y selecciona subconjuntos de fuentes para que el archivo se vea igual en todos los equipos.
  • Agregue marcadores, enlaces y metadatos del documento, como título, autor y palabras clave.
  • Proteja los archivos con contraseñas y permisos.
  • Firma digital de documentos (desde la versión 6.2)

El despliegue es monótono, y lo digo como un elogio. Todo es código administrado, así que el encargado de operaciones nunca tiene que instalar Chrome sin interfaz gráfica en un servidor ni buscar una DLL de Ghostscript a las 2 de la madrugada. Simplemente se hace referencia a un paquete NuGet, se sube y listo.

Ahora viene el truco. Solo tienes un lienzo y nada más. ¿Un párrafo largo llega hasta el margen inferior? Es tu problema. ¿Una tabla se extiende más allá de la primera página? También es tu problema, a menos que uses MigraDoc.

PDFsharp y MigraDoc: ¿Qué capa necesitas?

Mismo proveedor, mismo calendario de lanzamientos, pero tareas muy diferentes. MigraDoc Foundation está justo encima de PDFsharp. En lugar de indicarle dónde va una cadena de texto, le proporcionas secciones, párrafos, tablas, encabezados, pies de página, estilos y algún que otro gráfico, y se encarga de ubicarlo todo. El resultado es un PDF. O un RTF, para el compañero que insiste en abrirlo todo en Word.

Mi forma abreviada de decirlo: PDFsharp es "coloca este texto en x=40, y=120". MigraDoc es "aquí tienes treinta filas y un encabezado que se repite; tú ordenas las páginas".

Tarea Mejor ajuste Por qué
Certificado o boleto de una página con posiciones fijas PDFsharp Control total sobre cada coordenada
Informe de varias páginas con tablas y encabezados continuos. MigraDoc Paginación y estilos automáticos
Factura con un número variable de artículos. MigraDoc Las tablas crecen y se dividen a lo largo de las páginas.
Sello, marca de agua o números de página en un PDF existente. PDFsharp MigraDoc solo crea documentos nuevos.
Combinar o dividir archivos existentes PDFsharp La importación de páginas es una función de PDFsharp.
Gráfico empresarial dentro de un informe MigraDoc Compatibilidad con gráficos integrada
Mixto: informe generado más una portada diseñada a medida. Ambos MigraDoc puede renderizar en una página PDFsharp

Los proyectos reales suelen acabar utilizando ambas opciones: texto principal mediante MigraDoc, una portada dibujada a mano o un sello en el PDF de algún proveedor a través de la capa inferior. De todas formas, es prácticamente imposible evitar instalar PDFsharp, ya que el paquete MigraDoc lo incluye como dependencia.

Explicación de las compilaciones de PDFsharp: compilación principal, GDI+ y WPF.

Los usuarios nuevos suelen quedarse atascados en el siguiente paso de la lista de paquetes en NuGet. PDFsharp 6 viene en tres versiones, cada una con su propio MigraDoc gemelo.

Paquete NuGet Construir Plataformas Fuentes e imágenes
PDFsharp / PDFsharp-MigraDoc Centro Windows, Linux, macOS Necesita un solucionador de fuentes; imágenes BMP, PNG, JPEG.
PDFsharp-GDI / PDFsharp-MigraDoc-GDI GDI+ Solo para Windows Utiliza las fuentes instaladas a través de System.Drawing.
PDFsharp-WPF / PDFsharp-MigraDoc-WPF WPF Solo para Windows Utiliza fuentes instaladas a través de WPF.

Los paquetes actuales están dirigidos a .NET 8, 9 y 10, además de .NET Standard 2.0 y .NET Framework 4.6.2. Así que prácticamente todo aquello en lo que todavía se está trabajando está cubierto, desde una herramienta WinForms obsoleta hasta una API ASP.NET Core totalmente nueva.

Aplicación de consola, API web, Docker, Azure Functions, ¿algo en Linux? Compilación básica. GDI+ o WPF solo tienen sentido para una aplicación de escritorio de Windows donde se necesitan fuentes del sistema o una vista previa en un control nativo. Alguien en Stack Overflow preguntó una vez si su aplicación de consola necesitaba la versión WPF. No la necesitaba.

Guía de PDFsharp

Cómo instalar PDFsharp desde NuGet en Visual Studio

Todavía encontrarás publicaciones en foros de la época de WinForms que te dicen que descargues un archivo ZIP, busques una DLL y añadas la referencia manualmente. Ignóralas. Instala PDFsharp a través de NuGet; el administrador de paquetes gestiona las versiones, así que no tienes que hacerlo tú.

  1. Abra su solución en Visual Studio y haga clic con el botón derecho en el proyecto en el Explorador de soluciones.
  2. Seleccione Administrar paquetes NuGet , cambie a la pestaña Examinar y busque "PDFsharp".
  3. Seleccione PDFsharp (versión básica) o PDFsharp-MigraDoc si también necesita el diseño del documento. Compruebe que el editor sea empira Software GmbH.
  4. Haz clic en Instalar y acepta la solicitud de licencia.
  5. Compila el proyecto una vez para confirmar que el paquete se ha restaurado correctamente.

Los usuarios de terminales pueden omitir hacer clic:

bash dotnet add package PDFsharp dotnet add package PDFsharp-MigraDoc

En la consola del administrador de paquetes, el comando es Install-Package PDFsharp. Y por favor, no mezcle compilaciones. Vi a un equipo perder toda una tarde por conflictos de tipos porque un proyecto hacía referencia a PDFsharp y otro proyecto vecino incluía PDFsharp-GDI.

Tu primer documento PDF con PDFsharp en C

A continuación se describe el programa más sencillo para generar un archivo PDF de una página. Se ejecuta en la versión Core de cualquier sistema operativo, siempre que se haya configurado un solucionador de fuentes (véase la siguiente sección).

```csharp
utilizando PdfSharp.Drawing;
utilizando PdfSharp.Pdf;

// PDFsharp 6.5+ requiere elegir una licencia antes del primer uso.
PdfSharpLicense.SetAgplLicense();

var documento = nuevo PdfDocument();
document.Info.Title = "Hola PDFsharp";

PdfPage página = documento.AddPage();
XGraphics gfx = XGraphics.FromPdfPage(page);

var font = new XFont("Arial", 20, XFontStyleEx.Bold);
gfx.DrawString("¡Hola, PDFsharp!", fuente, XBrushes.Black,
nuevo XRect(0, 0, page.Width.Point, page.Height.Point),
XStringFormats.Center);

documento.Guardar("hola.pdf");
```

Todos los programas de PDFsharp siguen esta estructura: documento, página, XGraphics, dibujar, guardar. Las unidades son puntos (1/72 de pulgada) y el origen se encuentra en la esquina superior izquierda. En la versión 6.2.x, elimine la línea de licencia. Esa API solo apareció en la versión 6.5.0.

Y la versión de MigraDoc:

```csharp
utilizando MigraDoc.DocumentObjectModel;
usando MigraDoc.Rendering;

var doc = nuevo Documento();
Sección sección = doc.AddSection();
sección.AddParagraph("¡Hola, MigraDoc!");

var renderizador = nuevo PdfDocumentRenderer { Document = doc };
renderizador.RenderDocumento();
renderer.PdfDocument.Save("hola-migradoc.pdf");
```

No hay coordenadas por ningún lado. Si le echas 500 párrafos, obtendrás la cantidad de páginas que sean necesarias, sin ningún código de paginación por tu parte.

Fuentes en la compilación principal de PDFsharp: El problema del solucionador

Si preguntas por ahí, la queja más frecuente será sobre las fuentes. Las compilaciones GDI+ y WPF simplemente leen las fuentes TrueType instaladas en Windows. La compilación Core no puede dar nada por sentado, ya que un contenedor Linux ligero a menudo no tiene fuentes utilizables. Por lo tanto, el primer despliegue de Docker suele terminar con una excepción que indica que no se encontró una fuente adecuada.

La solución es un solucionador de fuentes, una clase que implementa IFontResolver. Tiene dos métodos:

  • ResolveTypeface asigna una familia y un estilo solicitados (por ejemplo, "Arial", negrita) a un nombre de fuente.
  • GetFont devuelve los bytes sin procesar del archivo TTF para ese nombre de fuente.

Regístrelo una sola vez al iniciar la aplicación a través de GlobalFontSettings.FontResolver, antes de que se cree la primera fuente XFont.

```csharp
clase pública 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 = new AppFontResolver();
```

Cosas que conviene saber antes de que te encuentres con ellas:

  • Guarda tus archivos TTF en una carpeta llamada Fonts dentro del proyecto y configúralos para que se copien al directorio de salida, o incorpóralos como recursos para que la imagen contenedora siempre los incluya.
  • La versión 6.2.0 eliminó el antiguo CoreBuildFontResolver. En Windows o WSL2, puede restaurar un comportamiento similar con GlobalFontSettings.UseWindowsFontsUnderWindows, pero esto no tiene ningún efecto en Linux o macOS.
  • El repositorio oficial de ejemplos incluye un SubstitutingFontResolver que puedes copiar como punto de partida.
  • Antes de incorporar una tipografía comercial en los archivos generados, compruebe la licencia de la fuente. Las fuentes abiertas como Inter, Roboto o Noto evitan por completo este problema.

Una vez configurado el resolvedor, el resultado es idéntico en Windows, Linux y macOS.

Combinar, firmar y proteger archivos con PDFsharp 6

Muchos equipos nunca crean un documento desde cero. Utilizan la biblioteca para combinar, sellar o bloquear archivos que ya existen. La combinación se realiza en pocas líneas: abre cada archivo fuente en modo de importación y copia las páginas.

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

La división se realiza mediante el mismo bucle a la inversa, generando un archivo de salida por página o rango. Para mayor protección, document.SecuritySettings requiere una contraseña de usuario, una contraseña de propietario e indicadores de permisos (imprimir, copiar texto, etc.).

Dos características muy solicitadas finalmente llegaron a la versión 6.2:

  • Firmas digitales basadas en CMS. Se incluye un firmante predeterminado en un ensamblado PDFsharp.Cryptography independiente, y puede integrar el suyo propio implementando IDigitalSigner. La compatibilidad con servidores de marcas de tiempo funciona en .NET moderno, pero no en la compilación de .NET Framework.
  • Salida PDF/A para archivado. La documentación oficial describe que funciona "con algunas limitaciones" y que aún está en desarrollo, por lo que conviene validar el resultado con un verificador de PDF/A antes de confiar en él para el cumplimiento de la normativa.

Esa versión también incluyó glifos de emojis a color y una implementación MD5 administrada, lo cual es importante si se trabaja bajo las reglas FIPS o en Blazor.

Repositorio de PDFsharp, bifurcaciones de PdfSharpCore y versiones 1.x

Si buscas PDFsharp en GitHub, encontrarás varios proyectos con nombres casi idénticos. La historia es la culpable.

La antigua línea 1.x (1.50, 1.51) solo funcionaba en .NET Framework. Cuando salió .NET Core, la gente no quiso esperar y decidió adaptarlo por su cuenta. PdfSharpCore, iniciado por Stefan Steiger y posteriormente adoptado por otras bifurcaciones, es el más conocido. Eliminó GDI+ y logró que el código funcionara en Linux años antes de su lanzamiento oficial.

Luego llegó PDFsharp 6: una reescritura completa en .NET moderno con una compilación Core oficial multiplataforma. Las bifurcaciones perdieron gran parte de su razón de ser.

Proyecto Mantenedor Plataformas Estado
PDFsharp 6.x (repositorio empira/PDFsharp) empira Software GmbH .NET 8–10, .NET Standard 2.0, .NET Framework 4.6.2 Mantenimiento activo
PDFsharp 1.5x empira Software GmbH Solo para .NET Framework El código fuente se guarda en GitHub, pero ya no se mantiene.
PdfSharpCore y sus bifurcaciones Comunidad .NET Core / .NET Standard 2.0 Varía según la bifurcación, las actualizaciones son más lentas.
PDFsharp-MigraDoc 6.x empira Software GmbH Igual que PDFsharp 6 Mantenimiento activo

¿Y qué hay del debate sobre "PdfSharp vs PdfSharpCore" que no para de aparecer en Reddit? Es un proyecto nuevo con paquetes oficiales. Mantén una bifurcación solo si el código antiguo ya depende de ella y migrarla no merece la pena ahora mismo. Y si la documentación es escasa, consulta el repositorio de ejemplos de empira. Sus carpetas y archivos contienen ejemplos ejecutables, lo que es mucho mejor que adivinar.

¿PDFsharp es gratuito? Cambios en la licencia de PDFsharp 6.5

Durante la mayor parte de su existencia, sí. Tenía licencia MIT, lo que significa que su uso comercial prácticamente no conlleva restricciones. Todas las versiones, hasta la 6.2.4 inclusive, siguen teniendo esa licencia.

La versión 6.5.0 cambió eso. La biblioteca ahora tiene doble licencia:

  • Licencia AGPL (gratuita). Para activarla, llame a PdfSharpLicense.SetAgplLicense() antes de usar la biblioteca. La licencia AGPL exige que el código fuente esté disponible para los usuarios, incluidos aquellos que interactúan con el software a través de una red, por lo que no es adecuada para software como servicio (SaaS) de código cerrado.
  • Licencia comercial. Usted compra una clave de licencia al proveedor y la carga con PdfSharpLicense.LoadLicense(...). Esto elimina las obligaciones de la licencia AGPL.

A partir de la versión 6.5.0, tu código debe seleccionar una opción explícitamente. Las versiones preliminares de la 7.0 funcionan de la misma manera.

En la práctica:

  • Los proyectos de código abierto compatibles con AGPL pueden seguir utilizando la versión más reciente de forma gratuita.
  • Los productos de código cerrado pueden optar por comprar una licencia comercial o permanecer en la versión 6.2.x, que sigue bajo la licencia MIT. Permanecer en la versión actual implica perderse futuras correcciones, así que evalúe ese costo con objetividad.
  • Sea cual sea su elección, lea el texto de la licencia y obtenga la aprobación de su equipo legal. Esta guía no constituye asesoramiento legal.

Guía de PDFsharp

Dónde se queda corto PDFsharp y con qué combinarlo

La biblioteca cumple bien su función. Sin embargo, su función es limitada, y las mismas deficiencias se repiten en todos los hilos del foro.

  • PDFsharp no genera HTML ni CSS. Existe un complemento de la comunidad, HtmlRenderer.PdfSharp, pero solo admite HTML 4.01 y CSS nivel 2, por lo que no funcionará con diseños modernos que utilicen flexbox o cuadrícula. Los equipos que necesitan plantillas HTML suelen optar por un renderizador sin interfaz gráfica.
  • No se permite JavaScript. Los gráficos o el contenido creados en el lado del cliente no se pueden capturar.
  • No se renderiza a imágenes. PDFsharp no puede convertir una página PDF en un archivo PNG para miniaturas o vistas previas. Para ello, necesita un rasterizador independiente.
  • Extracción de texto limitada. Se puede recorrer el flujo de contenido, pero no existe una API de alto nivel que devuelva texto limpio con información de posición. PdfPig, una biblioteca de código abierto independiente, está diseñada específicamente para leer y extraer texto.
  • Compatibilidad parcial con formularios. El llenado sencillo de formularios AcroForm funciona; los formularios complejos con scripts son otra historia.
  • Las tablas necesitan MigraDoc. Con PDFsharp estándar, usted mismo calcula la altura de cada fila.

Eso no la convierte en una mala opción. Los documentos basados en datos, como facturas, extractos, etiquetas y certificados, son precisamente su nicho de mercado, y su tamaño es mínimo. Las copias exactas de páginas web, en cambio, no lo son.

PDFsharp para facturas y recibos de pago de criptomonedas

Los recibos son probablemente lo más común que se crea con PDFsharp. Los recibos de criptomonedas son un poco más complejos que los de tarjetas. La buena noticia es que, una vez que la pasarela de pago activa tu webhook (una llamada HTTP que se envía cuando cambia el estado del pago), ya tienes todos los datos. No necesitas buscar nada más.

Lo que yo le pondría:

  • Número de pedido o factura y datos del comerciante
  • Importe en criptomoneda y su equivalente en moneda fiduciaria en el momento del pago.
  • Moneda y red (por ejemplo, USDT en TRON frente a USDT en Ethereum)
  • Hash de la transacción, para que el cliente pueda verificarlo en un explorador de bloques.
  • Una dirección de monedero receptora abreviada y el tiempo de confirmación
  • Un código QR que enlaza con la página de la transacción o factura.

Utilice una fuente monoespaciada para hashes y direcciones. Los clientes las leen detenidamente, carácter por carácter, y en Arial, un cero y una O mayúscula parecen idénticos. Si el hash es demasiado ancho, ajústelo; el texto de 6 puntos no ayuda a nadie. Incruste las fuentes, guarde el archivo con el pedido y fírmelo si su contable le pide recibos.

Nada de eso cubre la gestión del cobro. Para ello, usarías una pasarela de pago como Plisio . Esta acepta BTC, USDT y muchas otras criptomonedas, genera la factura y llama a tu servidor cada vez que cambia el estado. Tu gestor envía la información a MigraDoc y el comprador recibe un recibo con tu logotipo mientras aún está en la página de agradecimiento.

Conclusión

Siempre vuelvo a PDFsharp por una razón: es pequeño y discreto. La versión Core funciona en cualquier entorno compatible con .NET, y MigraDoc se encarga del diseño cuando un lienzo no es suficiente. Hay tres cosas que conviene definir desde el principio: qué versión usar, cómo se cargan las fuentes y qué licencia tienes ahora que la versión 6.5 es AGPL. Imprime datos, no páginas web, y te durará años.

¿Alguna pregunta?

Generar PDFs a partir de código .NET, principalmente. Por ejemplo, facturas, informes, etiquetas de envío y certificados. También es útil para combinar y dividir archivos, o para añadir números de página y marcas de agua a PDFs creados por terceros. Con MigraDoc, los documentos extensos con tablas y gráficos tampoco suponen una tarea ardua.

Hasta la versión 6.2.4, sí, es MIT y se puede incluir en productos de pago. A partir de la versión 6.5.0, hay dos opciones. La opción AGPL es gratuita, pero requiere compartir el código fuente; la opción comercial tiene un coste y no requiere compartir el código fuente. El código de tu proyecto debe especificar cuál usar.

No. No incluye ningún motor HTML ni CSS. Existe un complemento de la comunidad llamado HtmlRenderer.PdfSharp que lo intenta, pero solo funciona con HTML 4.01 y CSS 2, por lo que cualquier diseño con flexbox o grid falla. Para páginas web reales, se utiliza un conversor basado en un navegador sin interfaz gráfica.

Mediante NuGet. Haz clic derecho en el proyecto en Visual Studio, selecciona "Administrar paquetes NuGet" y busca "PDFsharp". Desde la terminal, ejecuta `dotnet add package PDFsharp`. ¿Necesitas tablas y paginación? Agrega PDFsharp-MigraDoc. Olvídate de copiar manualmente las DLL.

Para corregir diseños y editar archivos existentes: PDFsharp. Para todo aquello donde el texto fluye, las tablas crecen y las páginas se dividen solas: MigraDoc. Sinceramente, probablemente terminarás usando ambos, y como MigraDoc se ejecuta sobre PDFsharp, funcionan bien juntos.

PDFsharp 6 es compatible con .NET 8, 9 y 10, además de .NET Standard 2.0 y .NET Framework 4.6.2. La versión Core funciona en Windows, Linux y macOS. Las versiones GDI+ y WPF solo están disponibles para Windows. ¿Vas a usar Linux? Configura primero un solucionador de fuentes o podrías tener problemas con las fuentes.

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.