Converta HTML para PDF com 06 linhas de Código

Java

09/04/2009

Sempre vejo pessoas procurando por ai como converter HTML para PDF, mas sempre as soluções são obscuras complicadas e não muito "limpas", as vezes requerendo bibliotecas proprietárias. Pois então vou lhe dar uma solução com apenas 06 linhas de código que salvará sua alma :+D. Lá vamos nós rápidos e rasteiros. Como o código é mediocremente pequeno vou colocar tudo aqui pra encher linguiça, até os imports
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.OutputStream;

import org.w3c.dom.Document;
import org.w3c.tidy.Tidy;
import org.xhtmlrenderer.pdf.ITextRenderer;

import com.lowagie.text.DocumentException;

/**
 * @Autor Eder Baum
 */
public class Html2Pdf {

	public static void convert(String input, OutputStream out) throws DocumentException{
        convert(new ByteArrayInputStream(input.getBytes()), out);
	}
	
	public static void convert(InputStream input, OutputStream out) throws DocumentException{
    	Tidy tidy = new Tidy();        	
    	Document doc = tidy.parseDOM(input, null);
        ITextRenderer renderer = new ITextRenderer();
        renderer.setDocument(doc, null);
        renderer.layout();       
        renderer.createPDF(out);        		
	}	

}
Se você contar o numero de linhas do 2º método convert, verá que há apenas 06 linhas como prometido, e para usar esta classe, o código é menor ainda:
OutputStream os = new FileOutputStream("C:\\hello.pdf");;
Html2Pdf.convert("<h1 style=\"color:red\">Hello PDF</h1>", os);        	
os.close();
Os jars que vc precisa são estes Tidy : http://jtidy.sourceforge.net XHTMLRenderer : https://xhtmlrenderer.dev.java.net/ Itext: http://www.lowagie.com/iText A beleza do código, você não precisa se preocupar com as coisas baixas, basta mandar HTML em não conformidade que o resto o código cuida. Espero que tenham divertido-se.
Ederbaum

Ederbaum

Curtidas 0

Melhor post

Ederbaum

Ederbaum

01/06/2016

Pessoal, o código original fui eu que escrevi a ANOS Atrás, mas de lá pra cá, muita coisa mudou ou ficou obsoleta. Segue um código atualizado e funcional:
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.ederbaum.io.pdf;

import com.ederbaum.io.IOUtil;
import com.itextpdf.text.BadElementException;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.XMLWorker;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import com.itextpdf.tool.xml.html.Tags;
import com.itextpdf.tool.xml.parser.XMLParser;
import com.itextpdf.tool.xml.pipeline.css.CSSResolver;
import com.itextpdf.tool.xml.pipeline.css.CssResolverPipeline;
import com.itextpdf.tool.xml.pipeline.end.PdfWriterPipeline;
import com.itextpdf.tool.xml.pipeline.html.AbstractImageProvider;
import com.itextpdf.tool.xml.pipeline.html.HtmlPipeline;
import com.itextpdf.tool.xml.pipeline.html.HtmlPipelineContext;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import com.itextpdf.text.pdf.codec.Base64;
import com.itextpdf.tool.xml.exceptions.CssResolverException;
import com.itextpdf.tool.xml.pipeline.html.ImageProvider;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;

/**
 *
 * @author Éder
 */
public class Html2Pdf {

    private final InputStream is;
    private ImageProvider imProvider;
    private CSSResolver cssResolver;

    public Html2Pdf(InputStream is) throws TransformerConfigurationException, TransformerException {
        this.is = is;
        cssResolver = XMLWorkerHelper.getInstance().getDefaultCssResolver(true);
        this.imProvider = new Base64ImageProvider();
    }   

    public Html2Pdf(String html) throws TransformerException {
        this(new ByteArrayInputStream(html.getBytes()));
    }

    public void setImageProvider(ImageProvider imProvider) {
        this.imProvider = imProvider;
    }

    public void addCss(String css) throws CssResolverException {
        cssResolver.addCss(css, Boolean.TRUE);
    } 

    

    public void convert(OutputStream file) throws DocumentException, IOException {       
        Document document = new Document();
        // step 2
        PdfWriter writer = PdfWriter.getInstance(document, file);
        // step 3
        document.open();
        // step 4        

        // HTML
        HtmlPipelineContext htmlContext = new HtmlPipelineContext(null);
        htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
        if (imProvider != null) {
            htmlContext.setImageProvider(imProvider);
        }

        // Pipelines
        PdfWriterPipeline pdf = new PdfWriterPipeline(document, writer);
        HtmlPipeline html = new HtmlPipeline(htmlContext, pdf);
        CssResolverPipeline css = new CssResolverPipeline(cssResolver, html);

        // XML Worker
        XMLWorker worker = new XMLWorker(css, true);
        XMLParser p = new XMLParser(worker);
        p.parse(is);

        // step 5
        document.close();
    }

    public void convert(File os) throws FileNotFoundException, IOException, DocumentException {
        try (OutputStream out = new BufferedOutputStream(new FileOutputStream(os))) {
            convert(out);
        }
    }

    public static void main(String[] args) throws IOException, FileNotFoundException, DocumentException, TransformerException, CssResolverException {
        //Html2Pdf pdf = new Html2Pdf(new File("C:/tmp/private/boleto_tmp.html"));
        Html2Pdf pdf = new Html2Pdf("<h1 style=\"color:red\">Tchau Querida</h1>");
        pdf.setImageProvider(new Base64ImageProvider());
        pdf.convert(new File("/out.pdf"));
    }

    static class Base64ImageProvider extends AbstractImageProvider {

        @Override
        public Image retrieve(String src) {
            int pos = src.indexOf("base64,");
            try {
                if (src.startsWith("data") && pos > 0) {
                    byte[] img = Base64.decode(src.substring(pos + 7));
                    return Image.getInstance(img);
                } else {
                    return Image.getInstance(src);
                }
            } catch (BadElementException | IOException ex) {
                return null;
            }
        }

        @Override
        public String getImageRootPath() {
            return null;
        }
    }

}

GOSTEI 1

Mais Respostas

Guilherme Zanetta

Guilherme Zanetta

09/04/2009

Eu utilizei este código dentro de uma classe que eu preciso, mas quando vou executar, da um erro dizendo que não existe uma função dentro do iText. Bom, fui pesquisar e vi que o iText mudou a assinatura do método e não manteve uma assinatura compatível afim de manter compatibilidade para versões anteriores. Gostaria de saber qual foram as versões dos pacotes jars que estas utilizando? Grato
GOSTEI 0
Paulo Santos

Paulo Santos

09/04/2009

Cara e se eu tenho uma imagem no HTML? uma tag:
<img src="sourceImage" />
Como proceder?
GOSTEI 0
Paulo Santos

Paulo Santos

09/04/2009

E como setar o chaset?
GOSTEI 0
Paulo Santos

Paulo Santos

09/04/2009

E antes que me esqueça parabens pela solução, aqui funcionou, execto as imagens e o charset que eu to testando com Tidy tidy.setCharEconding(int charset);
GOSTEI 0
Faiter

Faiter

09/04/2009

O problema que eu tive com as imagens que não apareciam no PDF, foram resolvidas modificando o caminho das imagens antes de passar para o componente que gera o PDF. No meu caso: ../imagens/imagem.jpg Para: Contexto/imagens/imagem.jpg Grande abraço a todos.
GOSTEI 0
Ederbaum

Ederbaum

09/04/2009

zanetta Os jars quue funcionan disponibilzei aqui: http://dl.getdropbox.com/u/15403/Html2PDF.zip
GOSTEI 0
Diego Pagliosa

Diego Pagliosa

09/04/2009

Opa, e quanto a estilização em css do PDF?? no caso eu programo em PHP e existe uma classe que renderiza o HTML e o CSS junto, estilizando como se fosse um página normal de qualquer site. Nessa método, ele estiliza o HTML de acordo com o css ou não?
GOSTEI 0
Carlos Fonseca

Carlos Fonseca

09/04/2009

[quote="diegoalpa"]Opa, e quanto a estilização em css do PDF?? no caso eu programo em PHP e existe uma classe que renderiza o HTML e o CSS junto, estilizando como se fosse um página normal de qualquer site. Nessa método, ele estiliza o HTML de acordo com o css ou não?
Esquece o itext, a licença dele é AGPL, a menos que você esteja usando para um projeto open source !, fora isso vai precisar comprar uma licença! Pessoal tem que verificar esse tipo de coisa antes de falar que a lib é livre, pois não é!
GOSTEI 0
Diego Pagliosa

Diego Pagliosa

09/04/2009

Sei que já um tanto velho o posto... mas tenho algumas tabelas no html e quando renderiza o conteúdo para pdf as tabelas são cortadas... teria alguma forma bacana de evitar isso? o conteúdo das tabelas são dinâmicas...
GOSTEI 0
Guilherme Goll

Guilherme Goll

09/04/2009

Opa, você conseguiu encontrar uma solução para este caso Giuliano? Estou com o mesmo problema de algumas tabelas sendo cortadas quando renderizo o html.
GOSTEI 0
Guilherme Goll

Guilherme Goll

09/04/2009

Bom dia! Alguem poderia me tirar uma duvida a respeito desse post: Nao estou conseguindo passar o nome do arquivo que preciso transformar para PDF, pois ele esta entendendo que o nome do arquivo e para conveter
GOSTEI 0
POSTAR