Categorias
componentes dicas dll imagem pdf thumbnail

Convertendo HTML em PDF

Nesse artigo veremos como converter um HTML em PDF. O HTML pode vir de uma p??gina externa quanto ser criado em tempo de execu????o. N??o haver?? muito o que explicar pois o c??digo em si, voc?? encontra a rodo pela net. Usaremos o componente iTextSharp.

Baixe o bin??rio e adicione em seu aplicativo (pasta Bin). Utilize o c??digo abaixo para fazer o processo de convers??o e exibi????o do PDF na tela:

using System;
using System.Web;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.html.simpleparser;

            // Captura ou atribui o HTML a ser convertido – no caso estou baixando de uma URL
            string html = new System.Net.WebClient().DownloadString(“http://thiagomarcal.blogspot.com/”);
            //string html = “Convertendo o HTML em PDF – Thiago Mar??al”;
            // Cria o documento aplicando o tamanho e margens
            Document documento = new Document(PageSize.A4, 80, 50, 30, 65);
            // Memory Stream para ser usado na convers??o e emiss??o
            MemoryStream ms = new MemoryStream();
            // Inicializa o gravador
            PdfWriter writer = PdfWriter.GetInstance(documento, ms);
            // L?? o HTML e atribui
            StringReader conteudo = new StringReader(html);
            // Objeto de convers??o do HTML
            HTMLWorker objeto = new HTMLWorker(documento);
            // Abre o documento
            documento.Open();
            // Aplica o parser para an??lise de convers??o
            // Geralmente aqui ocasiona muitos erros – irei explicar no post
            objeto.Parse(conteudo);
            // Fecha o documento
            documento.Close();
            // For??a o download do PDF gerado – se desej??vel voc?? pode salvar em disco tamb??m
            Response.Clear();
            Response.AddHeader(“content-disposition”, “attachment; filename=Documento_HTML.pdf”);
            Response.ContentType = “application/pdf”;
            Response.Buffer = true;
            Response.OutputStream.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);
            Response.OutputStream.Flush();
            Response.End();

Veja que a vari??vel html eu atribuo o HTML que desejo converter. O seu conte??do pode vir externamente ou posso atribuir um valor desejado.

Vamos aos problemas! Muitos v??o encontrar erro quando o objeto estiver fazendo o parser do HTML e muitos ir??o falhar. Acontece que, devido ?? complexidade do HTML que estiver trabalhando, o componente n??o consegue converter para o formato adequado ao que ele usa internamente. Por exemplo, o TABLE do HTML que usamos ?? “meio” diferente do TABLE que o componente usa. Esse ?? um dos exemplos… Ent??o prepara-se para fazer um tratamento adequado antes de fazer o parser. Eu sugiro o seguinte:

  1. Use express??o regular para validar seu HTML;
  2. Use express??o regular e/ou o HtmlAgilityPack para remover os JavaScripts;
  3. O conte??do a ser convertido deve ser apenas o que est?? dentro do body;
  4. Imagens, CSS e links devem conter o caminho completo (exemplo: http://thiagomarcal.blogspot.com/imgs/logo.png ao inv??s de ../imgs/logo.png), etc.
Ou seja, quanto mais simplificado for seu HTML mais r??pido e f??cil ser?? convertido em PDF. Uma observa????o bem clara ??: nem sempre ficar?? 100% que o esperado.
Uma dica que pode ser usada (e um armengue, claro!) ?? fazer o seguinte:
  1. Gere um thumb (imagem) do HTML que deseja converter (saiba como gerar um thumb de um HTML nesse post) e salve em disco;
  2. Atribua a vari??vel html com o conte??do <img src=”http://thiagomarcal.blogspot.com/imgs/thumb.png” />;
  3. Coloque o width e height na tag IMG o tamanho desejado (pode ser at?? o tamanho do papel).
Pronto! O parser ir?? identificar apenas uma imagem no HTML e gerar?? o PDF com ela. Mole-mole…
Categorias
correios dicas dll web-service

Acompanhar rastreamento de pedido dos Correios com C#

Mais um artigo para quem trabalha com loja virtual… Essa funcionalidade ?? bem importante para visualizar o rastreamento de um determinado pedido. Ao inv??s de mandar apenas o link com o c??digo para seu cliente, porque n??o enviar logo a tabela com os dados? Pois bem, ?? isso que iremos fazer! O c??digo ?? bem simples, r??pido e pode-se alterar para uma “infinidades” de formas afim de o colocar do jeito que deseja.

Abaixo temos um resumo do processo:

  1. Enviamos uma requisi????o GET com o n??mero do rastreamento;
  2. Obtemos os dados de retorno (p??gina completa);
  3. Capturamos apenas a tabela com os dados de rastreamento;
  4. Exibimos na tela.
Para capturar a apenas a tabela com os dados, pode-se fazer de v??rias formas (Express??o Regular, etc), mas preferi usar um componente que captura n??s de um documento HTML, o HtmlAgilityPack. Baixe ele e o coloque na refer??ncia de seu projeto (Bin). Agora ?? f??cil – utilize o c??digo abaixo:
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using HtmlAgilityPack;

protected void Page_Load(object sender, EventArgs e)
    {

        // Aplica campos de par??metros
        string codigo = “ES659170465BR”;
        string parametros = “?P_COD_UNI=” + codigo + “&P_LINGUA=001&P_TIPO=001”;
        // Cria o objeto de requisi????o
        WebRequest requisicao = WebRequest.Create(“http://websro.correios.com.br/sro_bin/txect01$.QueryList” + parametros);
        // Realiza a requisi????o
        HttpWebResponse retorno = (HttpWebResponse)requisicao.GetResponse();
        // L?? o objeto e faz a atribui????o ?? vari??vel
        StreamReader stream = new StreamReader(retorno.GetResponseStream(), Encoding.GetEncoding(“ISO-8859-1”));
        string dados = stream.ReadToEnd();
        // Transforma em um documento HTML – HtmlAgilityPack
        HtmlDocument html = new HtmlDocument();
        html.LoadHtml(dados);
        // Captura apenas a tabela contendo os dados do envio
        HtmlNode tabela = html.DocumentNode.SelectSingleNode(“//table”);
        if (tabela != null)
        {
            // Nesse caso voc?? pode capturar as colunas e linhas e trabalhar conforme desejar
            // Apenas fiz o loop para remover a formata????o inicial da tabela
            string htmlTable = “<table>”;
            // Extrai as linhas da tabela
            foreach (HtmlNode linha in tabela.SelectNodes(“//tr”))
                htmlTable += “<tr>” + linha.InnerHtml + “</tr>”;
            htmlTable += “</table>”;
            // Exibe a tabela de rastreamento
            Response.Write(“O hor??rio n??o indica quando a situa????o ocorreu, mas sim quando os dados foram recebidos pelo sistema, exceto no caso do <b>SEDEX 10 e do SEDEX Hoje, </b>em que ele  representa o hor??rio real da entrega.<br><br>” + htmlTable);
        }
        else
            Response.Write(“O nosso sistema n??o possui dados sobre o objeto informado. Se o objeto foi postado recentemente, ?? natural que seus rastros n??o tenham ingressado no sistema, nesse caso, por favor, tente novamente mais tarde. Adicionalmente, verifique se o c??digo digitado est?? correto: “ + codigo);
        // Finaliza objetos
        stream.Close();
        retorno.Close();

    }
No caso peguei o HTML da tabela contendo os dados e exibi de vez na tela. Poderia trat??-la de v??rias formas e uma delas poderia ser transformando-a em um DataTable ou DataSet para alguma manipula????o posterior. Veja nesse link aqui como fazer isso.
Os Correios n??o disp??e de Web-Service para esse tipo de consulta. Olhando na net, encontrei dois artigos: um de Manoel Campos e outro de Carlos Ferrari onde ambos disp??e de Web-Services (em PHP – mas pode ser consumido pelo ASP.NET) para esse tipo de consulta. Quem n??o quiser implementar e apenas consumir, podem us??-los que chega o mesmo objetivo.
Artigo bem f??cil e r??pido! Espero ter ajudado…
Categorias
dicas handler imagem thumbnail

Redimensionar imagens com alta qualidade em ASP.NET

O c??digo que irei mostrar nem precisarei de muita explica????o. Voc?? encontra a rodo a?? pela internet… Contudo, esse tem um pequeno diferencial: misturei o c??digo “pescado” da net com o incremento de Glenn Jones. O redimensionamento consiste em colocar no SRC da imagem o Generic Handler que faz todo o processo e gera a imagem. Ou seja, crie um arquivo ImageResize.ashx e coloque o seguinte c??digo abaixo:

using System;
using System.Drawing;
using System.IO;
using System.Web;


public class ImagemHandler : IHttpHandler {
    
    public void ProcessRequest (HttpContext context) {
        
        // Recupera os par??metros passados pela p??gina
        string strSrcImagemOriginal = “../upload/” + context.Request[“img”].ToString();
        string strAlturaImagemRedimensionar = “”;
        string strLarguraImagemRedimensionar = context.Request[“w”].ToString();        
        
        // Cria temporariamnte a imagem
        System.Drawing.Image imagemTemp = System.Drawing.Image.FromFile(context.Server.MapPath(strSrcImagemOriginal));
        
        // Vari??veis contendo o tamanho
        int srcWidth = imagemTemp.Width;
        int srcHeight = imagemTemp.Height;
        int thumbHeight;
        int thumbWidth;
        
        // Redimensiona a largura de forma proporcional
        if (context.Request[“w”] != null)
        {
            thumbWidth = int.Parse(strLarguraImagemRedimensionar);
            thumbHeight = (int)(thumbWidth * imagemTemp.Height) / imagemTemp.Width;
        }
        else
        {
            thumbWidth = imagemTemp.Width;
            thumbHeight = imagemTemp.Height;
        }
        
        // Redimensiona a altura
        if (context.Request[“h”] != null)
        {
            strAlturaImagemRedimensionar = context.Request[“h”].ToString();
            thumbHeight = int.Parse(strAlturaImagemRedimensionar);
            // Faz o rateio para o redimensionamento proporcional
            // Assim a altura e a largura nunca ir??o ultrapassar o tamanho limite
            double widthRatio = (double)imagemTemp.Width / (double)thumbWidth;
            double heightRatio = (double)imagemTemp.Height / (double)thumbHeight;
            double ratio = Math.Max(widthRatio, heightRatio);
            thumbWidth = (int)(imagemTemp.Width / ratio);
            thumbHeight = (int)(imagemTemp.Height / ratio);
        }
        imagemTemp.Dispose();
        
        // Envia para a mem??ria o objeto a ser trabalhado bem como o novo objeto
        Stream objStream = new StreamReader(context.Server.MapPath(strSrcImagemOriginal)).BaseStream;
        BinaryReader objBinaryReader = new BinaryReader(objStream);
        int i = (int)objStream.Length;
        byte[] arrBytes = objBinaryReader.ReadBytes(i);
        System.IO.MemoryStream memoryStream = new System.IO.MemoryStream(arrBytes);
        System.Drawing.Image image = System.Drawing.Image.FromStream(memoryStream);
        System.Drawing.Image thumbnail = new Bitmap(thumbWidth, thumbHeight);
        System.Drawing.Graphics graphic = System.Drawing.Graphics.FromImage(thumbnail);
        
        // Melhoria da nova imagem
        graphic.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
        graphic.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
        graphic.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
        graphic.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
        
        // Desenha a nova imagem
        graphic.DrawImage(image, 0, 0, thumbWidth, thumbHeight);


        // Aplica a codifica????o necess??ria
        System.Drawing.Imaging.ImageCodecInfo[] info = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();
        System.Drawing.Imaging.EncoderParameters encoderParameters;
        encoderParameters = new System.Drawing.Imaging.EncoderParameters(1);
        encoderParameters.Param[0] = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
        
        // Exibe a imagem em forma de JPG
        context.Response.ContentType = “image/jpeg”;
        thumbnail.Save(context.Response.OutputStream, info[1], encoderParameters);


    }


}

Mais dado do que isso ?? s?? de m??o beijada!

Categorias
dicas seguran??a

Verificando Vulnerabilidades em Aplica????es Web

Dica r??pida para analisar a seguran??a de aplica????es web… A Locaweb disponibilizou um artigo acerca do uso do WEBSECURIFY (da Google) na qual realiza uma bateria de testes sob uma aplica????o web e exibe as vulnerabilidades que possui. Mais informa????es leiam aqui. Bem interessante…

Categorias
ajax desempenho dicas web.config

Melhorando o desempenho de aplica????es ASP.NET que usam AJAX

Alguns dias atr??s estava lendo alguns artigos sobre desempenho e achei um artigo interessante de LanceZhang na qual ele fez uma bateria de testes em um website que possuia controles ASP.NET AJAX. O artigo voc?? l?? na ??ntegra aqui. Mas, como se diz na web, “?? old mas ?? gold!”, aproveitei o artigo dele para resumir (tirar o quente) das configura????es que ele aplicou e os colocarei aqui. Para quem sabe ingl??s o artigo ?? indispens??vel a leitura, pois l?? ele mostra com detalhes os testes realizados bem como os gr??ficos de desempenho.

Bem, o que ele fez? Encheu uma p??gina de controles AJAX e primeiramente mediu o tr??fego na rede averiguando a quantidade de bytes que s??o carregados quando feito uma requisi????o, sendo ela quando dado um PostBack ou apenas no Load da p??gina. Quem tem o Firefox, com certeza deve ter o plugin Firebug instalado. No Firebug tem uma sess??o de monitoramento de Rede que analisa as chamadas realizadas.

A primeira coisa notada ?? o tamanho da p??gina que estava muito grande. O uso do cache reduzia bruscamente o tamanho da p??gina sem fazer novos carregamentos desnecess??rios. Juntamente com a compress??o do ScriptResource que reduz ainda mais o tamanho dos scripts gerados.  Ent??o, no web.config, devemos aplicar a seguinte configura????o:

<system.web.extensions>
<scripting>
<scriptResourceHandler enableCompression=true enableCaching=true />
</scripting>
</system.web.extensions>

Fa??a um novo teste e notar?? a diferen??a! Outro aplica????o de desempenho ?? a forma como o ScriptManager do AJAX ?? trabalhado. Ent??o ?? sugerido us??-lo com a seguinte configura????o:

<asp:ScriptManager ID=ScriptManagerAjax runat=server EnablePartialRendering=false ScriptMode=Release LoadScriptsBeforeUI=false>
</asp:ScriptManager>

Cuidado com o EnablePartialRendering! Fa??a o teste em sua aplica????o com os valores false ou true porque a depender do que voc?? usa em seu sistema isso muda muito no comportamento dos scripts. Por ??ltimo, voc?? pode usar o CompositeScript dentro do ScriptManager para agregar v??rias chamadas de scripts em uma s??. Veja l?? no site de LanceZhang como fazer, caso tenha interesse nessa parte e se isso ainda n??o foi o suficiente.

Agregado a isso, e fora do escopo, voc?? pode usar a compress??o/compacta????o do ViewState para minimizar o tamanho da p??gina. Voc?? pode encontrar artigos relacionados por a?? na net, mas aconselho dar uma lida nesse aqui ou esse a depender de como queira utilizar. Muitas vezes eu prefiro desabilitar o ViewState… Mais r??pido, s?? que com cautela!

Categorias
cep correios frete web-service

Calculando frete com Web-Service dos Correios

Muito utilizado, principalmente, em lojas virtuais, o c??lculo de frete ?? uma funcionalidade bastante importante para todo e qualquer sistema. Nesse artigo veremos como usufruir do Web-Service dos Correios e fazer o c??lculo de frete para um determinado peso, local e tipo de frete. Pelo Web-Service ?? poss??vel consultar SEDEX, e-SEDEX e PAC. Lembrando que, para o tipo e-SEDEX e outros, a empresa deve ter um contrato com os Correios para utilizar essa modalidade. Isso ser?? mostrado como informar o login dos Correios antes de fazer a consulta.

Antes de come??ar, veja abaixo as formas de consulta que os Correios disp??e (retirado do site):

Forma de acesso e resposta Defini????o Exemplos de uso Protocolos de Acesso e de Resposta
Webservice A consulta utiliza a tecnologia webservices ??? cole????o de protocolos e padr??es usados para troca de informa????es entre aplica????es Internet. Lojas virtuais 
Sistemas corporativos
Acesso e resposta via XML, SOAP e WSDL – protocolos dewebservices
Resultado XML A consulta retorna os dados em formato XML, para livre tratamento das informa????es pelo cliente. Lojas virtuais 
Sites de empresas
Acesso via post
Resposta padr??o XML
Resultado p??gina do cliente A consulta transfere as informa????es de resposta para uma p??gina do cliente, por ele especificada. Sites de empresas Acesso via post 
Resposta via get
Resultado p??gina dos Correios A resposta vem numa p??gina dos Correios, em formato de p??gina pop-up. Call-centers Acesso via post 
Resposta em p??gina dos Correios

Conforme explicado, vamos utilizar o Web-Service para consumir e obter a resposta desejada. Nesse link tem o manual com maiores detalhes acerca do uso. Vamos a implementa????o!

Crie/Abra um Web Site e clique com o direito sobre o projeto para abrir o menu. Escolha a op????o Add Web Reference… .

Informe a URL http://ws.correios.com.br/calculador/CalcPrecoPrazo.asmx e clique em Go. Aguarde a realiza????o da busca pelo Web-Service, renomeie o servi??o (caso deseje) e escolha Add Reference.

Veja que em seu projeto ir?? surgir uma pasta nova denominada App_WebReferences e seu web.config ter?? uma nova entrada. Agora, preparemos o seguinte m??todo (s??o apenas sugest??es, pode melhor??-la ou adequar a sua necessidade):

private string ConsultaWebService()
    {
        // Dados da empresa, se tiver contrato com os Correios
        string nCdEmpresa = string.Empty;
        string sDsSenha = string.Empty;
        // C??digo do tipo de frete – por padr??o deixei o SEDEX
        string nCdServico = “40010”;
        // Cep de origem e destino – apenas n??meros
        string sCepOrigem = “40280000”;
        string sCepDestino = “40280000”;
        // Peso total da encomenda – por padr??o deixei 1kg
        string nVlPeso = “1”;
        // Formato da encomenda – por padr??o deixei caixa
        int nCdFormato = 1;
        // Para encomenda do tipo PAC, deve-se preencher a dimens??o da embalagem
        decimal nVlComprimento = 0;
        decimal nVlAltura = 0;
        decimal nVlLargura = 0;
        decimal nVlDiametro = 0;
        // Informa se ?? por m??o pr??pria – por padr??o deixei N??o
        string sCdMaoPropria = “N”;
        // Valor declarado – por padr??o n??o informo
        decimal nVlValorDeclarado = 0;
        // Se desejo recebr aviso de recebimento – por padr??o n??o quero
        string sCdAvisoRecebimento = “N”;


        // Instancio o web-service
        Correios.CalcPrecoPrazoWS webServiceCorreios = new Correios.CalcPrecoPrazoWS();


        // Efetuo a requisi????o
        Correios.cResultado retornoCorreios = webServiceCorreios.CalcPrecoPrazo(nCdEmpresa, sDsSenha, nCdServico, sCepOrigem, sCepDestino, nVlPeso, nCdFormato, nVlComprimento, nVlAltura, nVlLargura, nVlDiametro, sCdMaoPropria, nVlValorDeclarado, sCdAvisoRecebimento);


        // Verifico se h?? retorno
        if (retornoCorreios.Servicos.Length > 0)
        {
            // Se deu tudo certo, ent??o retorna o valor
            if (retornoCorreios.Servicos[0].Erro == “0”)
                return “R$ “ + retornoCorreios.Servicos[0].Valor;
            else
                return retornoCorreios.Servicos[0].MsgErro;
        }
        else
            return “N??O FOI POSS??VEL CONSULTAR O SERVI??O DESEJADO!”;


    }

No caso, o array de servi??os veio apenas um pois informando na vari??vel nCdServico que era para consultar apenas SEDEX. Pode ser mais de um numa consulta separados por v??rgula, exemplo “40010,81019”.

A tabela de servi??os dispon??veis s??o:

C??digo  Servi??o
41106  PAC sem contrato
40010  SEDEX sem contrato
40045  SEDEX a Cobrar, sem contrato
40215  SEDEX 10, sem contrato
40290  SEDEX Hoje, sem contrato
40096  SEDEX com contrato
40436  SEDEX com contrato
40444  SEDEX com contrato
81019  e-SEDEX, com contrato
41068  PAC com contrato

Essas e outras informa????es voc?? encontra no manual dos Correios. Isso possibilita e facilita bastante ao programador na consulta e obten????o dessa informa????o. Nunca escrevi tanto a palavra Correios em minha vida… T??!