หน้าเว็บ

วันพุธที่ 8 พฤษภาคม พ.ศ. 2556

Exporter (export html to pdf): java

maven project




dependencies
at pom.xml
        <dependency>
            <groupId>com.lowagie</groupId>
            <artifactId>itext</artifactId>
            <version>2.1.0</version>
            <type>jar</type>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
            <type>jar</type>
        </dependency>
        <dependency>
            <groupId>org.xhtmlrenderer</groupId>
            <artifactId>core-renderer</artifactId>
            <version>R8</version>
            <type>jar</type>
        </dependency>
        <dependency>
            <groupId>ant</groupId>
            <artifactId>ant</artifactId>
            <version>1.6.5</version>
            <type>jar</type>
        </dependency>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>6.0</version>
            <scope>provided</scope>
        </dependency>
Exporter.java (Builder Pattern)
package com.blogspot.na5cent.htmltopdf;

import com.lowagie.text.pdf.BaseFont;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.commons.io.FileUtils;
import org.apache.tools.ant.filters.StringInputStream;
import org.w3c.dom.Document;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;

/**
 *
 * @author redcrow
 * @link : http://na5cent.blogspot.com/2013/05/exporter-convert-html-to-pdf-java.html
 * @createDate : 08/05/2013
 */
public class Exporter {

    private static final Logger LOG = Logger.getLogger(Exporter.class.getName());
    private String style = "";
    private Boolean landscape = false;
    private List<String> fonts;
    private String encoding = "UTF-8";
    private int fontSize = 14;
    private String content;
    private String fileName = "report";

    private Exporter(String content) {
        this.content = ieInnerHTML(content).replace("<br>", "<br/>");
    }

    public static Exporter from(String html) {
        return new Exporter(html);
    }

    /**
     * add style(CSS) into report
     *
     * @param stylePath
     * @return ReportUtils
     * @throws IOException
     */
    public Exporter addStyle(String stylePath) throws IOException {
        style += FileUtils.readFileToString(new File(stylePath), "UTF-8");
        return this;
    }

    /**
     * set font size for report (default font size is "14pt")
     *
     * @param size
     * @return Exporter
     */
    public Exporter setFontSize(int size) {
        fontSize = size;
        style += "*{font-size:" + this.fontSize + "pt;}";
        return this;
    }

    /**
     * set file name for report (default file name is "report")
     *
     * @param fileName
     * @return Exporter
     */
    public Exporter setFileName(String fileName) {
        this.fileName = fileName;
        return this;
    }

    /**
     * @param fonts (path of font) (default location is "class path")
     * @return Exporter
     */
    public Exporter setFont(List<String> fonts) {
        this.fonts = fonts;
        return this;
    }

    /**
     * @param font (path of font) (default location is "class path")
     * @return Exporter
     */
    public Exporter addFont(String font) {
        if (fonts == null) {
            fonts = new ArrayList<String>();
        }
        fonts.add(font);
        return this;
    }

    /**
     * set encoding for report (default encoding is "UTF-8")
     *
     * @param encoding
     * @return Exporter
     */
    public Exporter setEncoding(String encoding) {
        this.encoding = encoding;
        return this;
    }

    public void toPDF(HttpServletResponse response) throws Exception {
        response.setContentType("application/pdf");
        response.setCharacterEncoding(encoding);
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".pdf");

        DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        String source = removeBlank(getReportContent());
        System.out.println("source : " + source);
        Document doc = builder.parse(new StringInputStream(source, encoding));

        ITextRenderer renderer = new ITextRenderer();
        if (fonts != null) {
            ITextFontResolver fontResolver = renderer.getFontResolver();
            for (String font : fonts) {
                fontResolver.addFont(font, BaseFont.IDENTITY_H, true);
            }
        }

        renderer.setDocument(doc, null);
        renderer.layout();
        OutputStream outputStream = null;
        try {
            outputStream = response.getOutputStream();
            renderer.createPDF(outputStream);
        } finally {
            if (outputStream != null) {
                outputStream.close();
            }
        }
    }

    public void toCSV(HttpServletResponse response) {
        response.setContentType("text/csv");
        response.setCharacterEncoding(encoding);
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".csv");

        ServletOutputStream outputStream = null;
        try {
            outputStream = response.getOutputStream();
            outputStream.print(formatData(content));
        } catch (IOException ex) {
            LOG.log(Level.SEVERE, null, ex);
        } finally {
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException ex) {
                LOG.log(Level.SEVERE, null, ex);
            }
        }
    }

    public void toExcel(HttpServletResponse response) {
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding(encoding);
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xls");

        ServletOutputStream outputStream = null;
        try {
            outputStream = response.getOutputStream();
            InputStream inputStream = new StringInputStream(removeHref(getReportContent()), "UTF-8");
            int byteInt;
            byte[] buf = new byte[1024];
            while ((byteInt = inputStream.read(buf)) != -1) {
                outputStream.write(buf, 0, byteInt);
            }
        } catch (IOException ex) {
            LOG.log(Level.SEVERE, null, ex);
        } finally {
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException ex) {
                LOG.log(Level.SEVERE, null, ex);
            }
        }
    }

    public void toTxt(HttpServletResponse response) {
        response.setContentType("text/plain");
        response.setCharacterEncoding(encoding);
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".txt");

        ServletOutputStream outputStream = null;
        try {
            outputStream = response.getOutputStream();
            outputStream.print(formatData(content));
        } catch (IOException ex) {
            LOG.log(Level.SEVERE, null, ex);
        } finally {
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException ex) {
                LOG.log(Level.SEVERE, null, ex);
            }
        }
    }

    /**
     * set landscape display (default is "Portrait")
     *
     * @return Exporter
     */
    public Exporter toLandscape() {
        landscape = true;
        return this;
    }

    /**
     * set portrait display (default is "Portrait")
     *
     * @return Exporter
     */
    public Exporter toPortrait() {
        landscape = false;
        return this;
    }

    //==========================================================================
    private String ieInnerHTML(String html) {
        StringBuffer stringBuffer = new StringBuffer();

        //replace uppercase html tag
        Pattern compile = Pattern.compile("<\\/?\\w+((\\s+\\w+(\\s*=\\s*(?:\".*?\"|'.*?'|[^'\">\\s]+))?)+\\s*|\\s*)\\/?>");
        Matcher matcher = compile.matcher(html);
        while (matcher.find()) {
            matcher.appendReplacement(stringBuffer, matcher.group().toLowerCase());
        }
        matcher.appendTail(stringBuffer);

        //replace attribute without quote (id=val -> id="val" )
        compile = Pattern.compile("\\=[a-zA-Z\\.\\:\\[\\]_\\-\\(\\)\\&\\$\\%#\\@\\!0-9]+[?\\s+|?>]");
        matcher = compile.matcher(stringBuffer.toString());
        stringBuffer = new StringBuffer();
        while (matcher.find()) {
            String text = matcher.group();
            matcher.appendReplacement(stringBuffer, "=\"" + text.substring(1, text.length() - 1) + "\"" + text.charAt(text.length() - 1));
        }
        matcher.appendTail(stringBuffer);

        return stringBuffer.toString();
    }

    private String removeBlank(String content) {
        return content.replaceAll("&nbsp;", "");
    }

    private String getReportContent() {
        if (landscape) {
            style += "@page {size: 11.69in 8.27in;}";
        } else {
            style += "@page {size: 8.27in 11.69in;}";
        }

        StringBuilder builder = new StringBuilder();
        builder.append("<html><head><style type='text/css'>");
        builder.append(style);
        builder.append("</style></head><body>");
        builder.append(content);
        builder.append("</body></html>");
        
        System.out.println("html : " + content);

        return builder.toString();
    }

    private String formatData(String input) {
        // replace " with “
        String regexp = "[\"]";
        String output = input.replaceAll(regexp, "“");
        //HTML
        output = output.replaceAll("\n", "");
        output = output.replaceAll(">[\\s]+", ">");
        output = output.replaceAll("<tr", "\n<tr");

        regexp = "</t[d|h]>[^>]*<t[d|h]";
        output = output.replaceAll(regexp, "</td>,<td");
        regexp = "<[^\\<]+\\>";
        output = output.replaceAll(regexp, "");
        return output;
    }

    private String removeHref(String input) {
        String regexp = "<[^<]a+>";
        String output = input;
        output = output.replaceAll(regexp, "");
        regexp = "<a[^<]+>";

        output = output.replaceAll(regexp, "");
        return output;
    }
}

Example to use
ToPdfService.java
package com.blogspot.na5cent.htmltopdf;

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *
 * @author redcrow
 */
@WebServlet(urlPatterns = "/toPdfService")
public class ToPdfService extends HttpServlet {
    private static final Logger LOG = Logger.getLogger(ToPdfService.class.getName());

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            request.setCharacterEncoding("UTF-8");
            String html = request.getParameter("html");
             
            //**********************************************************************
            Exporter.from(html) 
                    .addStyle(getServletContext().getRealPath("barStyle.css"))
                    .addFont("ANGSAU.TTF")
                    .addFont("ANGSAUB.TTF")
                    .toPDF(response);
            //**********************************************************************

        } catch (Exception ex) {
            LOG.log(Level.SEVERE, null, ex);
        }
    }
}

index.jsp (ส่ง html ไปยัง server เพื่อแปลงเป็น pdf)
<%-- 
    Document   : index
    Created on : May 7, 2013, 7:24:56 PM
    Author     : redcrow
--%>

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <link href="barStyle.css" rel="stylesheet"/>
        <script src="jquery.js"></script>
        <script src="barChart.js"></script>
        <script>
            var bar = new BarChart({
                title : 'na5cent bar chart',
                xText : 'x text',
                yText : 'y text',
                colors : ['red', 'green'],
                averageText : '',
                height: 200,
                width : 300,
                meaning: ['mean1', 'mean2'],
                data: [
                    {
                        name: 'name1',
                        bar: [
                            {
                                name: 'd11',
                                value: 20
                            },
                            {
                                name: 'd12',
                                value: 50
                            }
                        ]
                    },
                    {
                        name: 'name2',
                        bar: [
                            {
                                name: 'd21',
                                value: 10
                            },
                            {
                                name: 'd22',
                                value: 80
                            }
                        ]
                    },
                    {
                        name: 'name3',
                        bar: [
                            {
                                name: 'd31',
                                value: 80
                            },
                            {
                                name: 'd32',
                                value: 40
                            }
                        ]
                    },
                    {
                        name: 'name4',
                        bar: [
                            {
                                name: 'd41',
                                value: 100
                            },
                            {
                                name: 'd42',
                                value: 67
                            }
                        ]
                    }
                ]
            });


            $(function() {
                $('#bar').html(bar.html());
            });


            function copydata() {
                $('#html').html(bar.html());
            }
        </script>
    </head>
    <body>
        <div id="bar"></div>
        <form method="post" action="${pageContext.request.contextPath}/toPdfService">
            <textarea id="html" name="html"></textarea>
            <button type="submit" onclick="copydata();">send</button>
        </form>
    </body>
</html>

พอดี barChart ผมเขียนเองน่ะครับ เดี๋ยวไว้ว่างๆ ผมจะเอา code มา share ให้ดูครับ ^___^

ไม่มีความคิดเห็น:

แสดงความคิดเห็น