首页 > 其他分享 >多图片生成PDF(二)HTML生成PDF

多图片生成PDF(二)HTML生成PDF

时间:2022-12-08 18:01:25浏览次数:48  
标签:String import html 生成 HTML new PDF document com

HTML生成PDF
一、html生成pdf需要引入jar包
在pom.xml中引入如下jar包

<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>html2pdf</artifactId>
    <version>3.0.3</version>
</dependency>
<dependency>
    <groupId>org.xhtmlrenderer</groupId>
    <artifactId>flying-saucer-pdf</artifactId>
    <version>9.1.18</version>
</dependency>

<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.4.2</version>
</dependency>

<dependency>
    <groupId>org.eclipse.birt.runtime.3_7_1</groupId>
    <artifactId>com.lowagie.text</artifactId>
    <version>2.1.7</version>
</dependency>
<dependency>
    <groupId>com.itextpdf.tool</groupId>
    <artifactId>xmlworker</artifactId>
    <version>5.5.13</version>
    <scope>compile</scope>
</dependency>

二、Java代码

import cn.qcdoc.common.core.exception.BaseException;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import com.itextpdf.tool.xml.XMLWorker;
import com.itextpdf.tool.xml.css.StyleAttrCSSResolver;
import com.itextpdf.tool.xml.html.CssAppliers;
import com.itextpdf.tool.xml.html.Tags;
import com.itextpdf.tool.xml.parser.XMLParser;
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 com.itextpdf.tool.xml.pipeline.html.LinkProvider;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * html转PDF
 *
 * @author: wx
 * @date: 2022/11/21
 */
public class HtmlPdfDemo {
    public static String MakeHtml(List<String> listPath, String distPath, String templatePath){
        String fileame = "test.html";
        try {
            String templateContent = "";
            // 读取模板文件
            FileInputStream fileinputstream = new FileInputStream(templatePath);
            int length = fileinputstream.available();
            byte bytes[] = new byte[length];
            fileinputstream.read(bytes);
            fileinputstream.close();
            templateContent = new String(bytes);
            StringBuilder sbPath = new StringBuilder();
            for (String path : listPath) {
                String imgs = "<img src=\""+path+"\"/>"+"\n"+"<div style='page-break-before: always;'>\n" +
                        "\t\t</div>";
                sbPath.append(imgs);
            }
            String str = sbPath.toString().replace("\\", "/");
            //把模板页面上的 ###image_list### 替换成 img 里的内容
            templateContent = templateContent.replaceAll("###image_list###", str);
            // 生成的html文件保存路径。
            fileame = distPath + fileame;
            // 建立文件输出流
            FileOutputStream fileoutputstream = new FileOutputStream(fileame);
            byte tag_bytes[] = templateContent.getBytes();
            fileoutputstream.write(tag_bytes);
            fileoutputstream.close();
        } catch (Exception e) {
            throw new BaseException("创建html失败!");
        }
        return fileame;
    }

    /**
     * 创建PDF文件
     * @author: wx
     * @date: 2022/12/8
     * @param: htmlPath html路径
     * @param: outPdfPath 生成pdf路径
     * @param: imagePath 图片路径
     * @returns: void
     */
    public static void writeToOutputStreamAsPDF(String htmlPath, String outPdfPath, String imagePath) throws Exception {
        File targeFile = new File(outPdfPath);
        if(targeFile.exists()) {
            targeFile.delete();
        }
        //定义pdf文件尺寸,采用A4横切
        Document document = new Document(PageSize.A4, 20, 20, 20, 20);// 左、右、上、下间距
        //定义输出路径
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(outPdfPath));
        PdfReportHeaderFooter header = new PdfReportHeaderFooter("", 8, PageSize.A4);
        writer.setPageEvent(header);
        writer.addViewerPreference(PdfName.PRINTSCALING, PdfName.NONE);
        document.open();
        // HTML 设置
        HtmlPipelineContext htmlContext = getHtmlPipelineContext(imagePath, null);
        // Pipelines
        PdfWriterPipeline pdf = new PdfWriterPipeline(document, writer);
        HtmlPipeline html = new HtmlPipeline(htmlContext, pdf);
        CssResolverPipeline css = new CssResolverPipeline(new StyleAttrCSSResolver(), html);
        // XML Worker
        XMLWorker worker = new XMLWorker(css, true);
        XMLParser p = new XMLParser(worker);
        p.parse(new FileInputStream(htmlPath));
        document.close();
    }

    /**
     * html 设置
     * @author: wx
     * @date: 2022/10/13
     * @param: imagePath
     * @param: cssAppliers
     * @returns: com.itextpdf.tool.xml.pipeline.html.HtmlPipelineContext
     */
    private static HtmlPipelineContext getHtmlPipelineContext(String imagePath, CssAppliers cssAppliers) {
        HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers);
        htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
        htmlContext.setImageProvider(new AbstractImageProvider() {
            public String getImageRootPath() {
                return imagePath;
            }
        });
        htmlContext.setLinkProvider(new LinkProvider() {
            public String getLinkRoot() {
                return imagePath;
            }
        });
        return htmlContext;
    }

    public static void main(String[] args) throws Exception {
        List<String> listPath = new ArrayList<>();
        listPath.add("1665989812537.jpg");
        listPath.add("1665989815178.jpg");
        String distPath = "upload\\depot\\electronic\\23335\\NJ01TYQABYM\\";
        String templatePath = "upload\\depot\\table.html";
        String outFilePath = "upload\\depot\\electronic\\23335\\NJ01TYQABYM\\test.pdf";
        String htmlPath = MakeHtml(listPath, distPath, templatePath);
        writeToOutputStreamAsPDF(htmlPath, outFilePath, distPath);
    }
}

/**
 * 调整pdf样式
 *
 * @author: wx
 * @date: 2022/10/13
 */
class PdfReportHeaderFooter extends PdfPageEventHelper {

    /**
     * 页眉
     */
    public String header = "";

    /**
     * 文档字体大小,页脚页眉最好和文本大小一致
     */
    public int presentFontSize = 12;

    /**
     * 文档页面大小,最好前面传入,否则默认为A4纸张
     */
    public Rectangle pageSize = PageSize.A4;

    /**
     * 模板
     */
    public PdfTemplate total;

    /**
     * 基础字体对象
     */
    public BaseFont bf = null;

    /**
     * 利用基础字体生成的字体对象,一般用于生成中文文字
     */
    public Font fontDetail = null;


    /**
     * @param: yeMei 页眉字符串
     * @param: presentFontSize 数据体字体大小
     * @param: pageSize  页面文档大小,A4,A5,A6横转翻转等Rectangle对象
     * @returns:
     */
    public PdfReportHeaderFooter(String yeMei, int presentFontSize, Rectangle pageSize) {
        this.header = yeMei;
        this.presentFontSize = presentFontSize;
        this.pageSize = pageSize;
    }

    /**
     * 文档打开时创建模板
     * @author: wx
     * @date: 2022/10/14
     * @param: writer
     * @param: document
     * @returns: void
     */
    public void onOpenDocument(PdfWriter writer, Document document) {
        // 页尾 共 页 的矩形的长宽高
        total = writer.getDirectContent().createTemplate(50, 50);
    }

    /**
     * 关闭每页的时候,写入页眉,写入'第几页共'这几个字。
     * @author: wx
     * @date: 2022/10/14
     * @param: writer
     * @param: document
     * @returns: void
     */
    public void onEndPage(PdfWriter writer, Document document) {
        try {
            if (bf == null) {
                bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);
            }
            if (fontDetail == null) {
                fontDetail = new Font(bf, presentFontSize, Font.NORMAL);// 数据体字体
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 1.写入页眉
        ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_LEFT, new Phrase(header, fontDetail), document.left(), document.top() + 20, 0);
        // 2.写入前半部分的 第 X页/共
        int pageS = writer.getPageNumber();
        String foot1 = "第 " + pageS + " 页 /共";
        Phrase footer = new Phrase(foot1, fontDetail);
        // 3.计算前半部分的foot1的长度,后面好定位最后一部分的'Y页'这俩字的x轴坐标,字体长度也要计算进去 = len
        float len = bf.getWidthPoint(foot1, presentFontSize);
        // 4.拿到当前的PdfContentByte
        PdfContentByte cb = writer.getDirectContent();
        // 5.写入页脚1,x轴就是(右margin+左margin + right() -left()- len)/2.0F 再给偏移20F适合人类视觉感受,否则肉眼看上去就太偏左了 ,y轴就是底边界-20,否则就贴边重叠到数据体里了就不是页脚了;注意Y轴是从下往上累加的,最上方的Top值是大于Bottom好几百开外的。
        ColumnText.showTextAligned(cb, Element.ALIGN_CENTER, footer, (document.rightMargin() + document.right() + document.leftMargin() - document.left() - len) / 2.0F + 20F, document.bottom() - 16, 0);
        // 6.写入页脚2的模板(就是页脚的Y页这俩字)添加到文档中,计算模板的和Y轴,X=(右边界-左边界 - 前半部分的len值)/2.0F + len , y 轴和之前的保持一致,底边界-20
        cb.addTemplate(total, (document.rightMargin() + document.right() + document.leftMargin() - document.left()) / 2.0F + 20F, document.bottom() - 16); // 调节模版显示的位置

    }

    /**
     * 关闭文档时,替换模板,完成整个页眉页脚组件
     * @author: wx
     * @date: 2022/10/14
     * @param: writer
     * @param: document
     * @returns: void
     */
    public void onCloseDocument(PdfWriter writer, Document document) {
        // 7.最后一步了,就是关闭文档的时候,将模板替换成实际的 Y 值,至此,page x of y 制作完毕,完美兼容各种文档size。
        total.beginText();
        total.setFontAndSize(bf, presentFontSize);// 生成的模版的字体、颜色
        String foot2 = " " + (writer.getPageNumber() - 1) + " 页";
        total.showText(foot2);// 模版显示的内容
        total.endText();
        total.closePath();
    }
}

三、生成PDF文件

总结:
html生成pdf的时候,如果失败了,要检查对应的包是否引入错误,或者少引入jar。

本博客借鉴了网上的例子,在这里非常感谢其他博主的博客,让我在工作中解决了大量图片生成pdf的功能。

标签:String,import,html,生成,HTML,new,PDF,document,com
From: https://www.cnblogs.com/why0703/p/16966867.html

相关文章

  • 多图片生成PDF(一)多图片生成HTML
    多图片生成HTML一、准备前提1、准备一个html模板<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"/><metaname="viewport"content="width=d......
  • swagger 接口文档转 pdf
    步骤1、先把swagger导出swagger.json文件2、windows目录挂载注意下,比如windows目录D:\swagger得写成/D/swagger,swagger.json文件放在D:\swagger目录下,执行......
  • 用pageOffice控件实现 office word文档在线另存为pdf的功能
    用pageOffice控件实现officeword文档在线另存为pdf的功能1应用场景OA办公中,经常要将word文档转存为pdf方法,方式文档的查看。怎么实现word文档的转存为pdf呢?2实现方......
  • SourceGenerator 使用姿势(1):生成代理类,实现简单的AOP
    SourceGenerator已经出来很久了,也一直在关注。之前观摩大佬 xljiulang 的 WebApiClient 使用SourceGenerator生成接口代理类,深受启发,准备拿过来用看看(发出白嫖的声......
  • 如何在Visual Studio Code运行HTML的代码?
    1.VisualStudioCodeVisualStudioCode是微软推出的一个源代码编辑器。它在Windows、macOS和Linux上都能使用。可以通过它用各种编码语言来编写和编辑代码。在Visua......
  • 快速生成Vue2模板
    1.点击文件,再点击首选项,然后选择用户片段; 2.在弹出来的输入框中,选择第一行vue.json或者第二行新建全局代码片段文件都可,都是为了打开vue.json文件;  3.显示这种情......
  • 给PDF加密码真的是安全的吗,这里告诉你真相!
    PDF加密的原理所谓的PDF加密,就是给您的PDF文件加一个密码保护,其他人打开的时候,需要输入密码,那它具体是什么做的呢,我们来看看吧!PDF加密的算法简介RC4是对称流密码(即,可以......
  • 一个HTML5的图表库框架
    ​​http://www.rgraph.net/​​​RGraphisachartslibrarythatusesJavascriptandHTML5todrawandsupportsovertwentydifferenttype......
  • 一个模仿HTML5功能的jquery控件
    原文:http://www.matiasmancini.com.ar/html5form_en.php大致将要点翻译下:在HTML5中,验证输入框等都可以不用JAVASCRIPT就能实现了,现在只有少部分浏......
  • 十二、NHibernate之代码生成工具
    说明​这篇文章是完全转载自李永京的博客我看了下,也跟着实际操作了下,生成代码确实很方便,但是生成的代码却很难令人满意,不论从代码量还是从结构抑或复杂度来说,对我都是很大的......