Pruebas en un entorno real
Pruebe en producción sin marcas de agua.
Funciona donde lo necesites.
*Este artículo ha sido escrito por Jeff Fritz, una reconocida autoridad en desarrollo .NET.
En este artículo, Jeff revisa y compara la biblioteca IronPDF con otras tres bibliotecas PDF líderes para C#.NET: Aspose, SyncFusion e iTextPdf.
Estoy investigando toda la experiencia del desarrollador interactuando con tres productos comerciales de gestión de PDF para desarrolladores y comparándolos con la experiencia IronPDF. Compararemos y calificaremos cada producto en las siguientes áreas:
Cadencia de publicación y desarrollo de funciones
Concluiremos con una puntuación final de las herramientas.
Los desarrolladores tienen un mundo de productos PDF entre los que elegir. ¿Cómo pueden separar los productos y elegir el adecuado para su proyecto? Los desarrolladores de C# buscan en 3 lugares principales cuando investigan herramientas de software: motores de búsqueda, GitHub y NuGet. Buscaremos "PDF Software C#" en DuckDuckGo, un motor de búsqueda privado, y buscaremos estas herramientas PDF en GitHub, así como en NuGet.org. NuGet es el repositorio de paquetes .NET
Producto | DuckDuckGo | GitHub | NuGet |
---|---|---|---|
IronPDF | 5 | No se ha encontrado | 5 |
Aspose | 22 | 37 | 3 |
SyncFusion | 49 | N/A | 8 |
iTextPDF | No se ha encontrado | 40 | 7 |
Notas:
He limitado la búsqueda a los 100 primeros resultados de cada servicio y no he podido localizar el repositorio GitHub de IronPDF ni el sitio web de iText en DuckDuckGo. SyncFusion no dispone de un repositorio GitHub con ejemplos de creación de PDF.
Cada uno de los productos tiene un enfoque diferente para la adquisición de productos desde sus sitios web.
IronPDF lo deja claro con un botón de descarga en la portada
Los botones de descarga dirigen a NuGet.org y a las instrucciones estándar de instalación de paquetes .NET.
Aspose tiene un enlace en la página principal en el que debe elegir un idioma y, a continuación, se le ofrecen detalles sobre esa versión del producto y un botón de descarga.
A continuación, Aspose le pedirá que descargue las herramientas con una página que contiene instrucciones NuGet y varios párrafos de material promocional
SyncFusion tiene su biblioteca de gestión de PDF archivada en "Procesamiento de documentos - PDF". Su subsitio tiene el siguiente aspecto:
A continuación, debe rellenar un formulario para crear una cuenta en su sitio web con su dirección de correo electrónico, número de teléfono y nombre de la empresa. SyncFusion verifica tu correo electrónico con un mensaje de texto y luego te permite descargar un instalador para su software. También puedes instalar un paquete de prueba desde NuGet, pero dicen que el instalador proporciona el "producto completo". En los días siguientes a registrarme en el sitio web de SyncFusion, he recibido 2 correos electrónicos y 2 llamadas telefónicas ofreciéndome ayuda para empezar. Los correos electrónicos y las llamadas telefónicas fueron amables, pero las llamadas telefónicas me parecieron un poco invasivas.
iTextPDF lo deja claro con un producto y un enlace a su producto:
La pantalla de descarga ofrece tres opciones para descargar, con requisitos para registrarse con número de teléfono, correo electrónico, cargo y nombre de la empresa.
El volumen de opciones de iText me pareció abrumador y no estaba seguro de qué descargar. Elegí iText 7 y me llevó a otra pantalla para elegir entre nueve productos relacionados con PDF para descargar. Una vez más, esto me pareció confuso y me dejó inseguro sobre qué bibliotecas y herramientas necesitaba para mi proyecto.
Recibí un correo electrónico de seguimiento de iText con un enlace a su portal de clientes y una contraseña generada. Intenté utilizar su portal con las credenciales proporcionadas, pero no pude acceder al sitio.
Con cualquier biblioteca que un desarrollador descargue, la licencia determinará si puede utilizar el producto con su proyecto y cómo. Una licencia más permisiva permitirá distribuir la herramienta con una aplicación móvil o de escritorio, y las licencias más restrictivas pueden limitar el uso de la herramienta a su ejecución únicamente en un servidor protegido.
IronPDF proporciona un botón claro en la página principal, junto al botón "Descarga gratuita de NuGet" que enlaza con los términos de la licencia. La página resultante deja muy claro cuántos desarrolladores están cubiertos y el número de proyectos con los que se puede utilizar el producto. Existe una restricción sobre el número de oficinas que puede tener una organización. La redistribución del software como producto SaaS o aplicación nativa requiere una tasa de licencia adicional.
Aspose tiene 6 modelos de licencia disponibles En paquetes sin asistencia, con asistencia o con asistencia y asesoramiento. Encontré sus opciones bastante confusas, ya que también hay limitaciones en cuanto a los tipos de proyectos con los que se puede utilizar el producto, el número de desarrolladores con licencia y el tamaño de la organización.
Proyectos de sitios web de cara al público, incluido el soporte:
Inclusión | IronPDF | Syncfusion | AsposePDF | iText |
---|---|---|---|---|
1 sitio web 1 desarrollador 1 ubicación Ayuda | $749 | $2,495 | $5,394 | |
10 sitios web 10 promotores 10 emplazamientos Ayuda | Licencia profesional | $13,990 | $28,771 | |
Sitios web ilimitados Ayuda | Licencia ilimitada | N/A | $25,785+ (por año) |
SyncFusion tiene una tarifa única para su producto File Formats que incluye soporte para todos los tipos de aplicaciones .NET. La tarifa se cobra por desarrollador, con una reducción de tarifa para el segundo año de contrato. No hay limitaciones basadas en el tamaño de una organización o el número de proyectos con los que se utiliza el producto. También tienen un licencia comunitaria disponible para empresas en fase inicial
iText tiene varios productos disponibles que son de código abierto, pero hacen parecer que es necesario comprar una licencia para utilizar el producto.
La opción de adquirir una licencia comercial conduce a una pantalla en la que no aparece ninguna opción de compra. Hay una herramienta de configuración que debes completar con información sobre tu ubicación, idioma, volumen de uso y productos que te gustaría utilizar. A continuación, la herramienta ofrece un presupuesto para la licencia comercial.
Si el producto está disponible en código abierto, ¿puedo utilizarlo sin ninguna opción de soporte comercial? No está claro hasta que se hace clic en su Sitio de la Comunidad iText 7 y descubre que está cubierta por la licencia AGPL, que te obliga a liberar el código fuente de las aplicaciones que escribas y que utilicen su biblioteca en este modelo. Es una opción interesante, pero podría confundir a los desarrolladores
Con los diferentes modelos de despliegue disponibles para cada producto, hay diferentes niveles de compatibilidad que se prometen en cada sitio web. Es necesario investigar más para determinar la compatibilidad con diferentes proveedores de alojamiento y herramientas de alojamiento como Docker.
Medio ambiente | IronPDF | Aspose | SyncFusion | iText |
---|---|---|---|---|
COM | Sí | |||
.NET Framework | Sí | Sí | Sí | Sí |
.NET 5 | Sí | Sí | Sí | |
.NET 6 | Sí | Sí | Sí | |
.NET Standard | Sí | Sí | Sí | |
Xamarin | Sí | Sí | ||
MAUI | Sí | |||
Azure | Sí | |||
AWS | Sí | Sí | ||
%Mac | Sí | |||
Linux | Sí | |||
Docker | Sí |
Aspose es el único producto que afirma funcionar con aplicaciones COM, normalmente una necesidad heredada de los desarrolladores. iText no enumera sus plataformas soportadas en su sitio web, y una exploración de sus paquetes NuGet indica soporte para las plataformas indicadas. SyncFusion ofrece compatibilidad con varios marcos de interfaz de usuario, pero no con versiones de ejecución específicas. iText fue el único producto, aparte de IronPDF, que afirmó ser compatible con un servicio en la nube, con un banner que destacaba la compatibilidad con AWS.
He revisado cada uno de los productos y su experiencia de "Primeros pasos", tal y como se describe en sus sitios web. Estas son las instrucciones para "crear tu primera aplicación con el producto" para cada uno de estos productos.
Pude instalar y empezar con una versión de muestra de IronPDF usando NuGet, y una línea de código. Muy práctico y no desordena mi sistema.
La muestra IronPDF en https://ironpdf.com/ funciona con una consola sencilla o una aplicación nativa que utilice .NET 6 y versiones anteriores. Crea y carga un nuevo PDF con un simple bloque de texto "Hola Mundo", completando un ejemplo de código de 5 líneas con la escritura del archivo.
El código de ejemplo es claro y funciona perfectamente con el formato .NET 6 / C# 10. El bloque de código en línea dispone de un botón "copiar en el portapapeles" que permite ejecutarlo en un abrir y cerrar de ojos.
El archivo se escribe en la carpeta bin/ bajo el proyecto, y para una muestra rápida funciona. Me hubiera gustado tenerlo escrito junto al archivo de código que acabo de escribir ya que algunas personas podrían no saber buscar en la carpeta bin/ para content.=
Tuve que instalar una gran descarga, de 217 MB, para empezar a utilizar las bibliotecas de Aspose en mi sistema. Esto no instaló ninguna aplicación, sino que simplemente colocó las bibliotecas para Aspose en el disco.
El ejemplo de Aspose se encuentra en su documentación, en la sección "Primeros pasos", por lo que es un poco más difícil de localizar. El ejemplo de código en https://docs.aspose.com/pdf/net/hello-world-example/ incluye algo de prosa a su alrededor que explica lo que el código intenta hacer y se siente un poco repetitivo con los comentarios en código.
El ejemplo de Aspose no funciona como está escrito y debe mejorarse. En mi revisión de su producto, me encontré con los siguientes problemas:
Tuve que descargar un archivo grande de 874 MB para empezar, y la instalación me obligó a iniciar sesión en un servidor Syncfusion para extraer y trabajar con las bibliotecas. El instalador creó una aplicación "Panel de control" que me permitió navegar por una serie de demos en disco.
La demo de SyncFusion se encuentra más o menos a la mitad de su página de producto en https://www.syncfusion.com/document-processing/pdf-framework/net con fondo azul y texto azul claro. Según Lighthouse, esto tiene poco contraste y no es accesible para algunos usuarios.
He pegado el código de Syncfusion en Visual Studio y no he conseguido que Visual Studio genere una "sentencia using" adecuada para los objetos a los que se hace referencia en el código de demostración. De hecho, cuando pedí a Visual Studio que intentara localizar y generar una sentencia using, me remitió a instalar un paquete de la competencia:
El código de la muestra de SyncFusion no hacía nada tal y como se presentaba en pantalla. El código de demostración escribe un PDF en un MemoryStream, un objeto que gestiona el contenido de los archivos en memoria. Modifiqué el código para escribir en un archivo en disco, y generó correctamente un archivo que contenía "Hola Mundo".
La demo de iText está escrita en un claro editor de código en medio de la página de inicio de su producto. https://itextpdf.com/products/itext-7/itext-7-community A diferencia de las otras demos, iText incluyó un enlace para ver el PDF generado para este código.
Se me pidió que descargara un paquete de instalación desde su portal de clientes, y un día después de registrarme recibí un correo electrónico a las 5 de la mañana con instrucciones para registrarme. Las credenciales no funcionaron, y en su lugar descargué e instalé los paquetes de la comunidad disponibles en NuGet.
El código de ejemplo proporcionado para iText7 no funciona tal y como está escrito. A este código también le falta un puñado de sentencias using, pero una vez añadidas la aplicación generó un archivo PDF y lo escribió en la carpeta bin/ del proyecto.
Este elemento de revisión investiga la API y las interacciones que los desarrolladores tendrán con la biblioteca. Cada una de estas herramientas tiene varias formas de crear documentos PDF e interactuar con ellos. Veamos cada uno de ellos.
La documentación del producto es lo que lo hará triunfar o fracasar a largo plazo entre los desarrolladores. A medida que se adentran en el tema y necesitan funciones más avanzadas, ¿con qué rapidez pueden encontrar ese material y se proporcionan ejemplos que ayuden a enseñar estos conceptos?
En cada uno de estos productos, busqué en su documentación API la posibilidad de añadir firmas digitales a un PDF.
Los documentos de la API son claros y están bien organizados, con una tabla de contenidos en el panel izquierdo con un filtro en vivo. El cuadro de búsqueda de la parte superior derecha también incluye un filtro en vivo, y devuelve rápidamente varios artículos sobre los distintos componentes que proporcionan funciones de Firma. El sitio de la API tiene un modo claro y otro oscuro, una buena característica que prefieren los desarrolladores.
El documento de la clase PdfSignature
describe el objeto pero no incluye ningún enlace a código de ejemplo. He buscado "signature" en el sitio web ironpdf.com y he encontrado código de ejemplo que hace referencia al objeto PdfSignature
en https://ironpdf.com/examples/digitally-sign-a-pdf/
La documentación de la API de Aspose me remitió a su clase PdfFileSignature cuando busqué Signature. Esta página, al igual que la de IronPDF, muestra los detalles de la clase PdfFileSignature
, pero no incluye ningún enlace a demos ni describe cómo utilizar la clase.
Volví a la página base de documentación de Aspose en https://docs.aspose.com/pdf/net/ y buscó la firma. A continuación, se me presentó una lista de los artículos pertinentes y hice clic en el artículo "Añadir firma en un archivo PDF" en https://docs.aspose.com/pdf/net/add-signature-in-pdf/
La página de documentación básica de SyncFusion para el producto de formatos de archivo PDF se encuentra en https://help.syncfusion.com/file-formats/pdf/overview y tardé unos cuantos clics en encontrarlo. No tuve que buscar mucho para encontrar la muestra de firma como portada de la documentación.
En el sitio web de SyncFusion no hay documentos API que admitan la función de firma digital.
La documentación de la API de iText es muy completa y se genera a partir de cada versión publicada. Es un aspecto estándar que verás en otras bibliotecas de Internet. La búsqueda de la firma encontró algunas clases con algunas grandes descripciones en torno a esas características, pero de nuevo no hay enlaces a las muestras.
He buscado en el sitio web de iText un ejemplo de firma y no lo he encontrado. En su lugar, me he encontrado con varios artículos de blog en los que se anuncian nuevas colaboraciones.
La API que pone a disposición cada una de las herramientas es muy descriptiva y cada una adopta su propio enfoque para dar al desarrollador pleno acceso a la creación y gestión del contenido de un documento PDF. Afortunadamente, todos los frameworks tienen sugerencias completas de autocompletar que proporcionan una gran documentación en línea mientras trabajas con sus herramientas en un editor de código moderno como Visual Studio o Visual Studio Code que proporciona capacidades de autocompletar.
Las API de IronPDF facilitan interacciones muy difíciles y complejas con comandos simplificados como "RenderHtmlAsPdf", pero siguen proporcionando un acceso profundo a la creación y colocación del contenido, la seguridad, los metadatos y los formularios del documento. Como desarrollador, estas API "cambian mi forma de pensar" sobre la representación de contenidos.
Los nombres y términos utilizados por las APIs de IronPDF dejan claro que se está renderizando un documento o construyendo un documento. Las propiedades de tiempo en algunos de los ajustes son enteros que representan milisegundos donde yo hubiera preferido un tipo nativo TimeSpan. Por último, me gustaría que los tipos Configuración y Opciones contaran con una API de configuración moderna y fluida como ésta:
var Renderer = new IronPdf.ChromePdfRenderer(options =\> {
RenderDelay = TimeSpan.FromSeconds(1)
});
var Renderer = new IronPdf.ChromePdfRenderer(options =\> {
RenderDelay = TimeSpan.FromSeconds(1)
});
options =\> { RenderDelay = TimeSpan.FromSeconds(1) }
'INSTANT VB WARNING: An assignment within expression was extracted from the following statement:
'ORIGINAL LINE: var Renderer = new IronPdf.ChromePdfRenderer(options =\> { RenderDelay = TimeSpan.FromSeconds(1) });
Dim Renderer = New IronPdf.ChromePdfRenderer(options)
Las API de SyncFusion son claras y ofrecen un control muy descriptivo sobre cómo interactuar con sus herramientas de conversión. No hay atajos aquí, todo es necesario, y usted debe decirle qué herramientas está utilizando sin valores predeterminados disponibles. Los ajustes son amplios y permiten un control preciso de todo, incluida la ubicación del renderizador WebKit en el disco.
Esta configuración adicional, aunque no es necesario en algunas instalaciones, ha causado problemas a la gente en el pasado y en las versiones futuras SyncFusion promete que no es un problema.
La API de Aspose es extremadamente verbosa y me hace preguntarme si están intentando que los desarrolladores sean más productivos. La cantidad de configuración necesaria para cargar un documento desde un sitio web es asombrosa, 10 líneas de código o el doble de líneas que SyncFusion (5).
Un ejemplo de esto es que Aspose no tiene APIs que le permitan especificar una URL para obtener y convertir.
iText tiene una API similar a Aspose, muy verbosa y permite la interacción directa con la escritura en el documento con diferentes tipos de datos, pero no está claro cómo crear secciones del documento. Con lo explícitas que son las API y la baja calidad de la documentación, trabajar con iText es, en el mejor de los casos, difícil.
A continuación quise analizar las capacidades de renderizado y velocidad de cada herramienta a la hora de convertir contenido HTML a PDF. He escrito un código que está disponible en mi repositorio GitHub que puedes revisar para saber más sobre cómo realicé cada una de estas pruebas. También he escondido allí una copia de cada uno de los PDF de resultados para que lo revise. Voy a probar cada producto para:
El sitio web de referencia es muy sencillo, sin CSS y sólo texto con enlaces e imágenes.
Se trataba de 3 simples líneas de código a ejecutar, y el rendimiento parecía bueno a 835ms. Sin embargo, cuando abrí el PDF, comprobé que ninguna de las imágenes se incluía en el renderizado, resultado decepcionante con la configuración por defecto.
Después de explorar un poco, me enteré de que podía añadir un retardo de renderizado, y con esta configuración pude renderizar un PDF que incluía las imágenes adecuadas en la página.
Con la versión de prueba de la herramienta, hay una marca de agua que se incluye en el PDF renderizado. En la versión con licencia completa, esta marca de agua no está presente
SyncFusion fue un viaje curioso y confuso. Su documentación hace referencia a varias formas diferentes de renderizar y entregar HTML y PDF con diferentes números de versión y diferentes marcos que requieren diferentes códigos y configuraciones, así como instalaciones de herramientas binarias para funcionar correctamente.
Al igual que en la demostración de IronPDF, SyncFusion no renderizó las imágenes de la página y entregó un PDF con márgenes muy pequeños.
Con la versión de prueba de la herramienta, hay una marca de agua que se incluye en el PDF renderizado. En la versión con licencia completa, esta marca de agua no está presente
Aspose tiene una serie de instrucciones muy claras sobre cómo utilizar sus herramientas. Sin embargo, basándose en la instrucciones en su sitio web para convertir un sitio web en PDF tienen un error importante que impide que la función funcione. Además, su herramienta en línea que convierte un sitio web en PDF ya no funciona.
La documentación de iText no es tan fácil de encontrar y tuvimos que leer un libro electrónico para obtener el código de ejemplo que buscábamos para ejecutar esta muestra. Sin cambios en el código, sin configuración adicional y con 4 líneas de código, hemos generado un PDF muy atractivo, sin marcas de agua y con buenos márgenes.
Herramienta utilizada | Velocidad en milisegundos (cuanto más baja, mejor) |
---|---|
IronPDF | 835ms |
SyncFusion | 1799ms |
Aspose | N/A |
iText | 2975ms |
Para esta prueba, vamos a utilizar ESPN.com, un sitio web de deportes que tiene una gran cantidad de CSS, imágenes y JavaScript en la página. Dado que Aspose no funcionó para la prueba simple, los omitiremos en adelante. Utilizaremos el mismo código que utilizamos en la última demostración para crear estas capturas, simplemente sustituyendo la dirección del sitio web.
Como referencia, aquí el aspecto de ESPN en el momento de esta prueba:
Las puntuaciones en la parte superior y el informe del estado del juego en el centro de la pantalla se colocan con JavaScript y todo el posicionamiento y los colores se manejan con CSS3.
El renderizado IronPDF fue capaz de duplicar y cargar fielmente el contenido dinámico, sin embargo, parece como si la página se hubiera renderizado para un dispositivo móvil con elementos de contenido divididos en segmentos separados y en mosaico.
SyncFusion realizó un renderizado similar "estilo móvil" con contenido en mosaico vertical. Sin embargo, hemos perdido varias imágenes que el sitio ESPN cargaba dinámicamente y también se ha perdido parte del formato de las fuentes:
Para esta prueba, iText se negaba a ejecutarse y lanzaba una NullReferenceException, impidiendo que intentara renderizar el sitio web.
Herramienta utilizada | Velocidad en milisegundos (cuanto más baja, mejor) |
---|---|
IronPDF | 835ms |
SyncFusion | 1799ms |
Aspose | N/A |
iText | 2975ms |
La prueba final es generar un PDF con campos de entrada de formulario basado en un sitio web. El sencillo formulario de suscripción al boletín que escribí está disponible en el repositorio de GitHub y se renderiza con Bootstrap 5 en Firefox de esta manera:
Nota:
el Estado es un combobox, el campo Teléfono es un campo telefónico, el Correo electrónico es un campo de correo electrónico y la Talla de zapato es un campo numérico.
Iron brilla realmente en esta prueba, ya que se renderiza rápidamente en un diseño similar para móviles, como demuestra el botón de menú hamburguesa de la parte superior derecha. Las marcas de agua a lo largo de la página son molestas en una versión de prueba, pero se eliminan en la versión con licencia completa.
Todos los campos de los cuadros de texto se muestran como campos de formulario PDF con los que puedo interactuar, excepto los botones de opción y la casilla de verificación del final. Los cuadros de texto no tienen ninguna validación particular o aplicación de contenido sobre ellos como lo hacen en el navegador
SyncFusion renderizó lo que parece ser la versión de escritorio completa del sitio web, ya que no hay botón de menú de hamburguesa presente. Los elementos de formulario representados aparecen como cuadrados, botones y cuadros en la pantalla, pero ninguno de ellos es un campo de entrada de datos PDF estándar. Los enlaces de la cabecera y el pie de página, aunque ocultos por la marca de agua, son clicables.
iText fue fácilmente el más rápido de los tres frameworks a la hora de renderizar el contenido. Sin embargo, esa velocidad tenía un precio. Su renderizado ofrecía etiquetas de anclaje que navegaban al hacer clic, pero no llegaban al sitio web original. Se perdía todo el formato de bootstrap y todos los campos de formulario se mostraban como simples cuadros.
Herramienta utilizada | Velocidad en milisegundos (cuanto más baja, mejor) |
---|---|
IronPDF | 835ms |
SyncFusion | 1799ms |
Aspose | N/A |
iText | 2975ms |
Cada uno de estos marcos dispone de capacidades de soporte y cadencia de publicación distintas. Para disponer de un marco viable, actualmente desarrollado y en crecimiento, que sea compatible con una mayor parte del estándar PDF, nos gustaría contar con asistencia en línea y calendarios de publicación regulares.
Desde el Sitio web de NuGet parece que IronPDF publica una versión cada 2-4 semanas. Dispone de opciones de asistencia por chat en directo y correo electrónico. Sería bueno ver un foro en línea o un servidor Discord / Slack para chatear con el soporte y otros miembros de la comunidad IronPDF.
Según NuGet publican una actualización de sus bibliotecas PDF una vez a la semana. SyncFusion cuenta con foros en línea y un sistema de tickets de asistencia en línea. No hay opciones de soporte de chat en vivo de SyncFusion.
Según NuGet Aspose.PDF se publica una vez al mes. Ofrecen un servicio de asistencia gratuito, un servicio de asistencia de pago y consultoría de pago. No veo que haya interacciones en directo ni interacciones comunitarias disponibles.
NuGet informa de que iText actualiza sus paquetes una vez cada 2-3 meses. Su único soporte disponible es a través de un gestor de incidencias JIRA en línea y un formulario de "contacto". No hay interacciones en directo ni foros alojados disponibles.
De cada sección de este documento, he clasificado los productos entre sí, siendo el 4 el mejor valorado.
Categoría | IronPDF | Aspose | SyncFusion | iText |
---|---|---|---|---|
Descubrimiento | 3 | 4 | 2 | 1 |
Adquisición | 4 | 3 | 2 | 1 |
Licencias | 3 | 2 | 4 | 1 |
Compatibilidad | 4 | 1 | 2 | 3 |
Primeros pasos | 4 | 1 | 2 | 3 |
API | 4 | 2 | 3 | 1 |
Documentación | 4 | 4 | 3 | 2 |
Renderizar sitios web | 4 | 0 | 3 | 2 |
Ayuda | 3 | 4 | 2 | 1 |
Total (cuanto más alto, mejor) | 33 | 21 | 23 | 15 |
Notas:
9 productos API .NET para sus documentos de oficina