Polly Retry (Como funciona para desenvolvedores)
Lidar de forma adequada com falhas transitórias, timeouts e exceções é crucial para construir aplicações robustas e resilientes. Polly é uma biblioteca .NET popular que oferece resiliência e recursos de tratamento de falhas transitórias. Dentre suas muitas funcionalidades, "tentativa e erro" é uma das políticas mais utilizadas.
Neste artigo, vamos explorar a política de repetição do Polly em C# , analisando seu uso e opções de configuração, além de fornecer exemplos práticos de código. Além disso, utilizaremos a biblioteca IronPDF para geração de PDFs com a opção Polly Retry para gerar um PDF dos resultados da solicitação do formulário.
O que é Polly Retry?
O Polly Retry é uma política fornecida pela biblioteca Polly que permite aos desenvolvedores repetir automaticamente operações que possam falhar devido a um erro ou falhas transitórias. Falhas transitórias são erros temporários que ocorrem devido a problemas de rede, indisponibilidade de serviço ou outros problemas transitórios.
Com a política de repetição do Polly, você pode definir regras para repetir operações, incluindo o número máximo de tentativas, o atraso entre várias tentativas e as condições para repetir uma solicitação com falha. Isso ajuda a criar aplicativos resilientes que podem se recuperar de falhas temporárias sem travar ou causar interrupções aos usuários finais.
Primeiros passos com o Polly: Tentar novamente
Antes de mergulharmos nos exemplos de código, vamos estabelecer um entendimento básico de como instalar e configurar o Polly em um projeto C#.
Instalando Polly
Você pode instalar o Polly através do Console do Gerenciador de Pacotes NuGet usando o seguinte comando:
Install-Package Polly
Ou via .NET CLI:
dotnet add package Polly
Adicionando Polly usando instruções
No seu arquivo C#, inclua o namespace Polly:
using Polly;
using Polly;
Imports Polly
Exemplo básico de política de repetição
Vamos começar com um exemplo simples em que repetimos uma operação que simula a busca de dados de um serviço remoto. Configuraremos uma política de repetição com um máximo de 3 tentativas e um tempo limite fixo de 2 segundos entre elas.
using System;
using System.Net.Http;
using Polly;
namespace PollyRetryExample
{
public class Program
{
public static void Main(string[] args)
{
// Define a retry policy that handles HttpRequestException with a maximum of 3 retries
var retryPolicy = Policy
.Handle<HttpRequestException>() // Specify the exception type to handle
.WaitAndRetry(
3, // Max retry attempts
retryAttempt => TimeSpan.FromSeconds(2), // Fixed retry delay
(exception, timeSpan, retryCount, context) =>
{
Console.WriteLine("Retry {0} due to {1}", retryCount, exception.Message);
});
try
{
// Execute the action within the context of the retry policy
retryPolicy.Execute(() =>
{
FetchDataFromRemoteService();
});
}
catch (Exception ex)
{
Console.WriteLine("Failed after 3 retries: {0}", ex.Message);
}
}
// Simulate fetching data that throws HttpRequestException
public static void FetchDataFromRemoteService()
{
throw new HttpRequestException("Failed to fetch data from remote service");
}
}
}
using System;
using System.Net.Http;
using Polly;
namespace PollyRetryExample
{
public class Program
{
public static void Main(string[] args)
{
// Define a retry policy that handles HttpRequestException with a maximum of 3 retries
var retryPolicy = Policy
.Handle<HttpRequestException>() // Specify the exception type to handle
.WaitAndRetry(
3, // Max retry attempts
retryAttempt => TimeSpan.FromSeconds(2), // Fixed retry delay
(exception, timeSpan, retryCount, context) =>
{
Console.WriteLine("Retry {0} due to {1}", retryCount, exception.Message);
});
try
{
// Execute the action within the context of the retry policy
retryPolicy.Execute(() =>
{
FetchDataFromRemoteService();
});
}
catch (Exception ex)
{
Console.WriteLine("Failed after 3 retries: {0}", ex.Message);
}
}
// Simulate fetching data that throws HttpRequestException
public static void FetchDataFromRemoteService()
{
throw new HttpRequestException("Failed to fetch data from remote service");
}
}
}
Imports System
Imports System.Net.Http
Imports Polly
Namespace PollyRetryExample
Public Class Program
Public Shared Sub Main(ByVal args() As String)
' Define a retry policy that handles HttpRequestException with a maximum of 3 retries
Dim retryPolicy = Policy.Handle(Of HttpRequestException)().WaitAndRetry(3, Function(retryAttempt) TimeSpan.FromSeconds(2), Sub(exception, timeSpan, retryCount, context)
Console.WriteLine("Retry {0} due to {1}", retryCount, exception.Message)
End Sub)
Try
' Execute the action within the context of the retry policy
retryPolicy.Execute(Sub()
FetchDataFromRemoteService()
End Sub)
Catch ex As Exception
Console.WriteLine("Failed after 3 retries: {0}", ex.Message)
End Try
End Sub
' Simulate fetching data that throws HttpRequestException
Public Shared Sub FetchDataFromRemoteService()
Throw New HttpRequestException("Failed to fetch data from remote service")
End Sub
End Class
End Namespace
Neste exemplo:
Handle<HttpRequestException>()especifica que queremos tratarHttpRequestExceptione tentar novamente a operação se ela ocorrer.WaitAndRetry()configura a política de repetição com 3 tentativas e um atraso fixo de 2 segundos entre as tentativas (duração máxima especificada).onRetryO delegado registra uma mensagem quando ocorre uma nova tentativa.

Configuração avançada da política de repetição
Recuo exponencial
O recuo exponencial é uma estratégia popular de repetição em que o atraso entre as solicitações e as novas tentativas aumenta exponencialmente. Polly fornece uma maneira conveniente de implementar o recuo exponencial usando WaitAndRetry().
var retryPolicy = Policy
.Handle<HttpRequestException>()
.WaitAndRetry(
retryCount: 3, // Max retry attempts
sleepDurationProvider: attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt)), // Exponential delay
onRetry: (exception, timeSpan, retryCount, context) =>
{
Console.WriteLine($"Retry {retryCount} due to {exception.Message}");
});
var retryPolicy = Policy
.Handle<HttpRequestException>()
.WaitAndRetry(
retryCount: 3, // Max retry attempts
sleepDurationProvider: attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt)), // Exponential delay
onRetry: (exception, timeSpan, retryCount, context) =>
{
Console.WriteLine($"Retry {retryCount} due to {exception.Message}");
});
Dim retryPolicy = Policy.Handle(Of HttpRequestException)().WaitAndRetry(retryCount:= 3, sleepDurationProvider:= Function(attempt) TimeSpan.FromSeconds(Math.Pow(2, attempt)), onRetry:= Sub(exception, timeSpan, retryCount, context)
Console.WriteLine($"Retry {retryCount} due to {exception.Message}")
End Sub)

Tente novamente com o disjuntor.
A combinação de novas tentativas com um disjuntor pode aumentar ainda mais a resiliência, evitando novas tentativas quando um serviço apresenta falhas constantes. Polly permite combinar facilmente políticas de repetição e de disjuntor.
// Define a circuit breaker policy
var circuitBreakerPolicy = Policy
.Handle<HttpRequestException>()
.CircuitBreaker(
exceptionsAllowedBeforeBreaking: 3, // Number of exceptions before breaking
durationOfBreak: TimeSpan.FromSeconds(30), // Time circuit stays open
onBreak: (ex, breakDelay) =>
{
Console.WriteLine($"Circuit broken due to {ex.Message}. Retry after {breakDelay.TotalSeconds} seconds.");
},
onReset: () =>
{
Console.WriteLine("Circuit reset.");
});
// Define a retry policy
var retryPolicy = Policy
.Handle<HttpRequestException>()
.WaitAndRetry(
retryCount: 3, // Max retry attempts
sleepDurationProvider: attempt => TimeSpan.FromSeconds(2), // Fixed retry delay
onRetry: (exception, timeSpan, retryCount, context) =>
{
Console.WriteLine($"Retry {retryCount} due to {exception.Message}");
});
// Combine both policies into a single policy wrap
var policyWrap = Policy.Wrap(circuitBreakerPolicy, retryPolicy);
// Define a circuit breaker policy
var circuitBreakerPolicy = Policy
.Handle<HttpRequestException>()
.CircuitBreaker(
exceptionsAllowedBeforeBreaking: 3, // Number of exceptions before breaking
durationOfBreak: TimeSpan.FromSeconds(30), // Time circuit stays open
onBreak: (ex, breakDelay) =>
{
Console.WriteLine($"Circuit broken due to {ex.Message}. Retry after {breakDelay.TotalSeconds} seconds.");
},
onReset: () =>
{
Console.WriteLine("Circuit reset.");
});
// Define a retry policy
var retryPolicy = Policy
.Handle<HttpRequestException>()
.WaitAndRetry(
retryCount: 3, // Max retry attempts
sleepDurationProvider: attempt => TimeSpan.FromSeconds(2), // Fixed retry delay
onRetry: (exception, timeSpan, retryCount, context) =>
{
Console.WriteLine($"Retry {retryCount} due to {exception.Message}");
});
// Combine both policies into a single policy wrap
var policyWrap = Policy.Wrap(circuitBreakerPolicy, retryPolicy);
' Define a circuit breaker policy
Dim circuitBreakerPolicy = Policy.Handle(Of HttpRequestException)().CircuitBreaker(exceptionsAllowedBeforeBreaking:= 3, durationOfBreak:= TimeSpan.FromSeconds(30), onBreak:= Sub(ex, breakDelay)
Console.WriteLine($"Circuit broken due to {ex.Message}. Retry after {breakDelay.TotalSeconds} seconds.")
End Sub, onReset:= Sub()
Console.WriteLine("Circuit reset.")
End Sub)
' Define a retry policy
Dim retryPolicy = Policy.Handle(Of HttpRequestException)().WaitAndRetry(retryCount:= 3, sleepDurationProvider:= Function(attempt) TimeSpan.FromSeconds(2), onRetry:= Sub(exception, timeSpan, retryCount, context)
Console.WriteLine($"Retry {retryCount} due to {exception.Message}")
End Sub)
' Combine both policies into a single policy wrap
Dim policyWrap = Policy.Wrap(circuitBreakerPolicy, retryPolicy)
Neste exemplo:
CircuitBreaker()define uma política de disjuntor que é interrompida após 3 exceções e permanece aberta por 30 segundos.Policy.Wrap()combina as políticas de disjuntor e de repetição em uma única política.

Introdução ao IronPDF
Visão geral da biblioteca IronPDF C# para PDF: trata-se de uma poderosa biblioteca C# que permite aos desenvolvedores criar, editar e manipular documentos PDF em seus aplicativos .NET . Seja para criar faturas, relatórios ou qualquer outro tipo de documento PDF, o IronPDF oferece uma API intuitiva que simplifica o processo.
Com o IronPDF, você pode converter facilmente páginas web HTML, CSS e até mesmo ASP.NET em PDF, tornando-o uma ferramenta versátil para uma ampla gama de aplicações. Além disso, oferece recursos avançados, como adicionar texto, imagens e elementos interativos a PDFs, bem como protegê-los com criptografia e assinaturas digitais.
O IronPDF se destaca na conversão de HTML para PDF , garantindo a preservação precisa dos layouts e estilos originais. É perfeito para gerar PDFs a partir de conteúdo da web, como relatórios, faturas e documentação. O IronPDF suporta a conversão de arquivos HTML, URLs e strings HTML brutas em arquivos PDF de alta qualidade.
using IronPdf;
class Program
{
static void Main(string[] args)
{
var renderer = new ChromePdfRenderer();
// 1. Convert HTML String to PDF
var htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>";
var pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent);
pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf");
// 2. Convert HTML File to PDF
var htmlFilePath = "path_to_your_html_file.html"; // Specify the path to your HTML file
var pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath);
pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf");
// 3. Convert URL to PDF
var url = "http://ironpdf.com"; // Specify the URL
var pdfFromUrl = renderer.RenderUrlAsPdf(url);
pdfFromUrl.SaveAs("URLToPDF.pdf");
}
}
using IronPdf;
class Program
{
static void Main(string[] args)
{
var renderer = new ChromePdfRenderer();
// 1. Convert HTML String to PDF
var htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>";
var pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent);
pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf");
// 2. Convert HTML File to PDF
var htmlFilePath = "path_to_your_html_file.html"; // Specify the path to your HTML file
var pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath);
pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf");
// 3. Convert URL to PDF
var url = "http://ironpdf.com"; // Specify the URL
var pdfFromUrl = renderer.RenderUrlAsPdf(url);
pdfFromUrl.SaveAs("URLToPDF.pdf");
}
}
Imports IronPdf
Friend Class Program
Shared Sub Main(ByVal args() As String)
Dim renderer = New ChromePdfRenderer()
' 1. Convert HTML String to PDF
Dim htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>"
Dim pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent)
pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf")
' 2. Convert HTML File to PDF
Dim htmlFilePath = "path_to_your_html_file.html" ' Specify the path to your HTML file
Dim pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath)
pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf")
' 3. Convert URL to PDF
Dim url = "http://ironpdf.com" ' Specify the URL
Dim pdfFromUrl = renderer.RenderUrlAsPdf(url)
pdfFromUrl.SaveAs("URLToPDF.pdf")
End Sub
End Class
Polly tenta novamente com o IronPDF
Ao trabalhar com o IronPDF, pode haver cenários em que você precise buscar dados de fontes externas ou executar operações complexas antes de gerar um PDF.
Nesses casos, você pode se deparar com falhas transitórias ou problemas temporários que podem levar a falhas na geração de PDFs. Para lidar com essas falhas transitórias de forma adequada, você pode usar o Polly Retry em conjunto com o IronPDF.
Instalando o IronPDF e o Polly
Antes de começar, certifique-se de instalar o pacote NuGet IronPDF em seu projeto.
Install-Package IronPdf
Usando o Polly Retry com o IronPDF
Vejamos um exemplo em que usamos o Polly Retry para lidar com falhas transitórias ao gerar um PDF usando o IronPDF. No exemplo a seguir, simularemos a obtenção de dados de uma API externa e, em seguida, a geração de um PDF com base nesses dados. Usaremos Polly Retry para executar a operação de busca de dados em caso de falhas.
using System;
using System.Net.Http;
using System.Threading.Tasks;
using IronPdf;
using Polly;
namespace IronPdfWithPollyRetry
{
public class Program
{
public static async Task Main(string[] args)
{
// Define a retry policy with async capability
var retryPolicy = Policy
.Handle<HttpRequestException>() // Specify exception type to handle
.WaitAndRetryAsync(
3, // Retry attempts
retryAttempt => TimeSpan.FromSeconds(2), // Calculated retry delay
(exception, timeSpan, retryCount, context) =>
{
Console.WriteLine("Retry " + retryCount + " due to " + exception.Message);
});
// Execute the retry policy asynchronously
var pdf = await retryPolicy.ExecuteAsync(async () =>
{
var data = await FetchDataFromExternalApiAsync(); // Fetch data from an external source
return GeneratePdfFromData(data); // Generate PDF using fetched data
});
pdf.SaveAs("GeneratedDocument.pdf");
}
// Simulate fetching data from an external API
static async Task<string> FetchDataFromExternalApiAsync()
{
await Task.Delay(100); // Simulate delay
throw new HttpRequestException("Failed to fetch data from external API");
}
// Generate PDF using IronPDF based on the fetched data
static PdfDocument GeneratePdfFromData(string data)
{
var htmlContent = "<html><body><h1>Data: " + data + "</h1></body></html>";
var renderer = new ChromePdfRenderer();
return renderer.RenderHtmlAsPdf(htmlContent);
}
}
}
using System;
using System.Net.Http;
using System.Threading.Tasks;
using IronPdf;
using Polly;
namespace IronPdfWithPollyRetry
{
public class Program
{
public static async Task Main(string[] args)
{
// Define a retry policy with async capability
var retryPolicy = Policy
.Handle<HttpRequestException>() // Specify exception type to handle
.WaitAndRetryAsync(
3, // Retry attempts
retryAttempt => TimeSpan.FromSeconds(2), // Calculated retry delay
(exception, timeSpan, retryCount, context) =>
{
Console.WriteLine("Retry " + retryCount + " due to " + exception.Message);
});
// Execute the retry policy asynchronously
var pdf = await retryPolicy.ExecuteAsync(async () =>
{
var data = await FetchDataFromExternalApiAsync(); // Fetch data from an external source
return GeneratePdfFromData(data); // Generate PDF using fetched data
});
pdf.SaveAs("GeneratedDocument.pdf");
}
// Simulate fetching data from an external API
static async Task<string> FetchDataFromExternalApiAsync()
{
await Task.Delay(100); // Simulate delay
throw new HttpRequestException("Failed to fetch data from external API");
}
// Generate PDF using IronPDF based on the fetched data
static PdfDocument GeneratePdfFromData(string data)
{
var htmlContent = "<html><body><h1>Data: " + data + "</h1></body></html>";
var renderer = new ChromePdfRenderer();
return renderer.RenderHtmlAsPdf(htmlContent);
}
}
}
Imports System
Imports System.Net.Http
Imports System.Threading.Tasks
Imports IronPdf
Imports Polly
Namespace IronPdfWithPollyRetry
Public Class Program
Public Shared Async Function Main(ByVal args() As String) As Task
' Define a retry policy with async capability
Dim retryPolicy = Policy.Handle(Of HttpRequestException)().WaitAndRetryAsync(3, Function(retryAttempt) TimeSpan.FromSeconds(2), Sub(exception, timeSpan, retryCount, context)
Console.WriteLine("Retry " & retryCount & " due to " & exception.Message)
End Sub)
' Execute the retry policy asynchronously
Dim pdf = Await retryPolicy.ExecuteAsync(Async Function()
Dim data = Await FetchDataFromExternalApiAsync() ' Fetch data from an external source
Return GeneratePdfFromData(data) ' Generate PDF using fetched data
End Function)
pdf.SaveAs("GeneratedDocument.pdf")
End Function
' Simulate fetching data from an external API
Private Shared Async Function FetchDataFromExternalApiAsync() As Task(Of String)
Await Task.Delay(100) ' Simulate delay
Throw New HttpRequestException("Failed to fetch data from external API")
End Function
' Generate PDF using IronPDF based on the fetched data
Private Shared Function GeneratePdfFromData(ByVal data As String) As PdfDocument
Dim htmlContent = "<html><body><h1>Data: " & data & "</h1></body></html>"
Dim renderer = New ChromePdfRenderer()
Return renderer.RenderHtmlAsPdf(htmlContent)
End Function
End Class
End Namespace
Este código C# demonstra como usar a biblioteca Polly para implementar políticas de repetição com o IronPDF para gerar um documento PDF. O método Main inicializa uma política de repetição usando o método WaitAndRetryAsync de Polly.
Esta política especifica que deve lidar com HttpRequestException e tentar novamente a operação até 3 vezes com um atraso de 2 segundos entre a tentativa inicial e as novas tentativas. Caso ocorra uma falha na nova tentativa, uma mensagem será exibida no console indicando o número da nova tentativa e a mensagem de exceção.
Dentro do método Main, a lógica da política de repetição é executada de forma assíncrona usando retryPolicy.ExecuteAsync(). Nessa execução, duas operações assíncronas são encadeadas: FetchDataFromExternalApiAsync() e GeneratePdfFromData(data).
Se FetchDataFromExternalApiAsync() falhar (como foi intencionalmente configurado para acontecer com uma exceção simulada), a política de repetição capturará o HttpRequestException, registrará a tentativa de repetição e tentará novamente a operação.
O método FetchDataFromExternalApiAsync() simula a busca de dados de uma API externa com atraso e lança intencionalmente um HttpRequestException para simular solicitações com falha.

Conclusão
Em conclusão, a política de repetição do Polly demonstra ser inestimável para lidar com falhas transitórias e garantir robustez em aplicações C#. Sua flexibilidade na configuração de tentativas de repetição, atrasos e condições permite que os desenvolvedores adaptem as estratégias de resiliência a requisitos específicos.
Seja usado de forma independente ou em conjunto com bibliotecas como o IronPDF , o Polly facilita a criação de aplicativos que se recuperam de falhas temporárias de forma eficiente, melhorando a experiência do usuário e a confiabilidade do software.
Ao integrar os recursos de repetição do Polly, os desenvolvedores podem construir sistemas mais resilientes, capazes de se adaptar e se recuperar de problemas transitórios, melhorando, em última análise, a qualidade e a confiabilidade geral de seus aplicativos.
IronPDF é a melhor biblioteca PDF em C# do mercado, e também oferece uma licença de avaliação. Os preços do IronPDF começam em US$ 699.
Para aprender sobre a conversão de HTML para PDF usando o IronPDF, visite o seguinte tutorial de conversão de HTML para PDF do IronPDF .
Perguntas frequentes
O que é Polly Retry em C#?
O Polly Retry é um recurso da biblioteca Polly em C# que permite aos desenvolvedores repetir automaticamente operações que falham devido a problemas temporários, como falhas de rede ou indisponibilidade de serviços. Isso ajuda a construir aplicações resilientes, lidando com falhas transitórias de forma adequada.
Como posso implementar uma política básica de repetição usando o Polly?
Você pode implementar uma política básica de repetição no Polly tratando exceções como HttpRequestException e configurando-a para tentar novamente no máximo três vezes, com um intervalo fixo de dois segundos entre cada tentativa.
Qual é a importância do recuo exponencial em Polly?
O backoff exponencial no Polly é usado para aumentar o atraso entre novas tentativas exponencialmente, o que ajuda a reduzir a carga nos serviços durante falhas. Isso pode ser implementado usando o método WaitAndRetry do Polly, que calcula os atrasos com base no crescimento exponencial.
Como faço para instalar o Polly em um projeto C#?
Você pode instalar o Polly em um projeto C# usando o Console do Gerenciador de Pacotes NuGet com o comando Install-Package Polly ou através da CLI do .NET com dotnet add package Polly .
A política de novas tentativas de Polly pode ser combinada com outras estratégias de resiliência?
Sim, o Polly permite combinar sua política de repetição com outras estratégias de resiliência, como um disjuntor, usando o método Policy.Wrap para aprimorar a resiliência do aplicativo e evitar novas tentativas quando um serviço falha consistentemente.
Como posso converter HTML para PDF em C#?
Você pode usar métodos do IronPDF, como RenderHtmlAsPdf , para converter strings HTML em PDFs. O IronPDF também suporta a conversão de arquivos HTML e páginas da web, incluindo CSS, para o formato PDF.
Por que a política de repetição do Polly é importante para aplicações C#?
A política de repetição do Polly é crucial para lidar com falhas transitórias em aplicações C#, garantindo robustez e melhorando a experiência do usuário, permitindo que o sistema se recupere de falhas temporárias sem travar.
Como implementar estratégias de repetição em um processo de geração de PDF?
Ao gerar PDFs, estratégias de repetição podem ser implementadas usando o Polly para lidar com falhas transitórias. Ao integrar os recursos de repetição do Polly com o IronPDF, você pode tentar operações de PDF várias vezes em caso de problemas temporários de rede ou de serviço.
Como faço para instalar uma biblioteca PDF em C#, como o IronPDF?
O IronPDF pode ser instalado através do Gerenciador de Pacotes NuGet com o comando Install-Package IronPDF , permitindo que você crie, edite e manipule documentos PDF em seus aplicativos C#.
Quais são os benefícios de usar o IronPDF para geração de PDFs?
O IronPDF oferece recursos poderosos para criar e manipular documentos PDF em aplicações .NET. Ele suporta a conversão de HTML, CSS e páginas web em PDFs, a adição de texto e imagens e a proteção de documentos com criptografia.




