Papiro: Uma biblioteca gratuita e nativa de HTML para PDF para .NET MAUI
Com dificuldades para gerar PDFs no .NET MAUI? Conheça o Papiro: uma biblioteca leve e de código aberto que converte HTML em PDFs de alta qualidade para Android e iOS. Crie faturas e relatórios profissionais sem a complexidade dos mecanismos de PDF tradicionais.
🚀 Apresentando Papiro: Uma Biblioteca Nativa e Gratuita de HTML para PDF no .NET MAUI
Desenvolver aplicativos móveis muitas vezes exige a geração de relatórios em PDF — notas fiscais, ordens de serviço, recibos ou documentos personalizados. O problema? As soluções existentes costumam ser complexas, caras ou excessivamente pesadas para necessidades simples.
É por isso que criei o Papiro, uma biblioteca gratuita e totalmente nativa para converter HTML em PDF em aplicações .NET MAUI, sem dependências externas, navegadores embutidos ou licenças comerciais caríssimas.

😩 O Problema das Soluções Atuais
Se você já tentou gerar PDFs em aplicativos móveis, provavelmente esbarrou em um destes cenários:
- Bibliotecas comerciais caras: Ferramentas como iText ou Syncfusion exigem licenças que podem custar milhares de dólares anualmente.
- APIs de baixo nível tediosas: Desenhar cada elemento do PDF manualmente (traçar linhas, calcular coordenadas x/y) é trabalhoso e torna a estilização um pesadelo.
- Soluções baseadas em navegador: Embarcar dependências pesadas como Chromium aumenta drasticamente o tamanho do seu app.
- Excesso de recursos desnecessários: Muitas bibliotecas MAUI são projetadas para cenários corporativos complexos quando tudo que você precisa é de um relatório simples.
💡 Por Que HTML é a Solução Ideal
HTML é a linguagem de templates perfeita para relatórios. Todo desenvolvedor conhece, é fácil de estilizar com CSS, pode ser pré-visualizado em qualquer navegador e oferece total flexibilidade de design.
O Papiro preenche essa lacuna: você escreve seu relatório em HTML, usa placeholders simples como {{nome_cliente}} para dados dinâmicos e gera um PDF nativo em segundos.
✨ Principais Funcionalidades
| Funcionalidade | Descrição |
|---|---|
| 🆓 100% Gratuito | Usa APIs nativas das plataformas Android e iOS. Sem iText, sem Chromium, sem Syncfusion. |
| ⚡ Extremamente Leve | Sem dependências externas pesadas. A biblioteca adiciona menos de 100KB ao seu app. |
| 📄 Paginação Automática | Divide automaticamente conteúdo longo em múltiplas páginas A4. |
| 🎨 Alta Qualidade Visual | Usa fator de escala 3x para garantir texto e imagens nítidos (~220 DPI). |
| 📱 Renderização Nativa | Utiliza o motor WebView da plataforma subjacente para renderização consistente. |
| 🔄 Async/Await Moderno | Interface assíncrona moderna com objetos de resultado detalhados. |
| 🏷️ Sistema de Templates | Suporte integrado para substituição de tags {{variavel}}. |
| ⏱️ Proteção contra Travamentos | Timeout embutido de 30 segundos previne travamentos infinitos na renderização. |
📦 Instalação Rápida
Adicione o pacote NuGet ao seu projeto .NET MAUI:
<PackageReference Include="CwSoftware.Papiro" Version="1.0.0" />
Registre o serviço no MauiProgram.cs:
using CwSoftware.Papiro;
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.UsePapiro(); // ✅ Adicione esta linha
return builder.Build();
}
🛠️ Exemplo Prático: Gerando uma Nota Fiscal
Veja como é simples gerar um PDF com dados dinâmicos usando o Papiro:
using CwSoftware.Papiro;
using System.Globalization;
public class InvoiceService
{
private readonly IHtmlToPdfService _pdfService;
public InvoiceService(IHtmlToPdfService pdfService)
{
_pdfService = pdfService;
}
public async Task<string?> GerarNotaFiscalAsync(string cliente, decimal total)
{
// 1. Defina seu template HTML
string template = @"
<html>
<head>
<style>
body { font-family: Helvetica, Arial, sans-serif; padding: 40px; }
h1 { color: #2c3e50; border-bottom: 3px solid #3498db; padding-bottom: 10px; }
.info { margin: 20px 0; background: #f8f9fa; padding: 15px; border-radius: 5px; }
.total { font-size: 24px; font-weight: bold; color: #27ae60; margin-top: 30px; text-align: right; }
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
th { background: #3498db; color: white; padding: 10px; text-align: left; }
td { border-bottom: 1px solid #ddd; padding: 10px; }
</style>
</head>
<body>
<h1>📋 Nota Fiscal de Serviço</h1>
<div class='info'>
<p><strong>Cliente:</strong> {{Cliente}}</p>
<p><strong>Data:</strong> {{Data}}</p>
<p><strong>Nº Nota:</strong> #{{Id}}</p>
</div>
<table>
<tr><th>Descrição</th><th>Valor</th></tr>
<tr><td>Consultoria Técnica</td><td>{{Total}}</td></tr>
</table>
<p class='total'>Valor Total: {{Total}}</p>
</body>
</html>";
// 2. Substitua as tags por dados reais
string html = HtmlTemplateHelper.ReplaceTags(template, new
{
Cliente = cliente,
Id = new Random().Next(1000, 9999),
Data = DateTime.Now.ToString("dd/MM/yyyy"),
Total = total.ToString("C2", new CultureInfo("pt-BR"))
});
// 3. Gere o PDF
var result = await _pdfService.ConvertAndSaveAsync(html, "nota-fiscal.pdf");
if (result.IsSuccess)
{
// Abra o PDF gerado usando o launcher nativo
await Launcher.Default.OpenAsync(new OpenFileRequest
{
Title = "Nota Fiscal",
File = new ReadOnlyFile(result.FilePath!)
});
return result.FilePath;
}
Console.WriteLine($"Erro: {result.ErrorMessage}");
return null;
}
}
🖼️ Lidando com Imagens e Logos
Usar imagens locais na geração de HTML para PDF pode ser complicado devido a restrições de acesso a arquivos em dispositivos móveis. O Papiro facilita isso fornecendo helpers para converter imagens em strings Base64, que podem ser incorporadas diretamente no seu HTML.
// De um arquivo local
string logoBase64 = await HtmlTemplateHelper.ImageToBase64Async("/storage/emulated/0/logo.png");
// De um recurso embutido no seu app
string logoBase64 = await HtmlTemplateHelper.EmbeddedResourceToBase64Async("MeuProjeto.Resources.Images.logo.png");
// Use no seu HTML
string template = @"<img src='{{LogoBase64}}' alt='Logo' width='150' />";
string html = HtmlTemplateHelper.ReplaceTags(template, new { LogoBase64 = logoBase64 });
📱 Suporte de Plataforma
- Android: API 21+ (Lollipop). Usa
PdfDocumente paginação manual via Canvas. - iOS: iOS 11+. Usa
UIMarkupTextPrintFormattereUIPrintPageRenderer.
📂 Conclusão
Gerar PDFs em aplicativos móveis não precisa ser caro ou complicado. O Papiro oferece uma solução simples, nativa e gratuita que aproveita o HTML — uma tecnologia que todo desenvolvedor já conhece — para criar documentos profissionais em segundos.
Se você está construindo aplicativos comerciais com .NET MAUI e precisa de relatórios, notas fiscais ou recibos, experimente o Papiro.
🔗 Links Úteis
- Repositório GitHub: CW-Software-Apps/Papiro-MAUI-HtmlToPDF
- Pacote NuGet: CwSoftware.Papiro
- App de Exemplo: Ver Exemplos
Se você achou esta biblioteca útil, por favor deixe uma estrela ⭐ no GitHub!
Perguntas frequentes
O Papiro depende do Chromium ou de algum navegador embutido para renderizar os PDFs?
Não. O Papiro usa o motor de renderização nativo de cada plataforma — PdfDocument com paginação manual via Canvas no Android, e UIMarkupTextPrintFormatter/UIPrintPageRenderer no iOS — e é por isso que a biblioteca adiciona menos de 100KB ao seu app, em vez do peso que vem ao embarcar o Chromium.
Como eu insiro dados dinâmicos, como nome do cliente ou total, no PDF?
Escreva seu HTML com tags {{placeholder}} (por exemplo, {{Cliente}}, {{Total}}) e chame HtmlTemplateHelper.ReplaceTags(template, new { ... }) passando um objeto anônimo cujos nomes de propriedade coincidam com os placeholders.
O que acontece se a renderização do HTML demorar demais ou travar?
O Papiro tem um timeout embutido de 30 segundos que evita um travamento infinito na renderização, então um template HTML malformado ou incomumente pesado falha de forma previsível em vez de travar a conversão indefinidamente.
Como adiciono um logo ou imagem local a um PDF gerado?
Primeiro converta a imagem para uma string Base64, usando HtmlTemplateHelper.ImageToBase64Async para um arquivo em disco ou EmbeddedResourceToBase64Async para um recurso embutido no seu app, e depois referencie essa string em uma tag <img src="{{LogoBase64}}"> no seu template.
O Papiro lida automaticamente com documentos maiores que uma página?
Sim — ele tem paginação automática que divide conteúdo longo em múltiplas páginas A4 sem nenhuma configuração extra.
Comentários
Ficou com uma dúvida ou encontrou um problema no código? Comente abaixo — eu leio e respondo pessoalmente.