富文本生成pdf-java

  1. 首先引入相关jar包

<dependency>

<groupId>com.itextpdf.tool</groupId>

<artifactId>xmlworker</artifactId>

<version>5.5.11</version>

</dependency>

<!-- 支持中文 -->

<dependency>

<groupId>com.itextpdf</groupId>

<artifactId>itext-asian</artifactId>

<version>5.2.0</version>

</dependency>

<!-- 支持css样式渲染 -->

<dependency>

<groupId>org.xhtmlrenderer</groupId>

<artifactId>flying-saucer-pdf-itext5</artifactId>

<version>9.1.16</version>

</dependency>

  1. 要保证富文本数据是完成html格式,不然很多数据样式会有问题,我的保存没有,统一添加的,前缀加了

 String replace1 ="<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd \">\n" +
                "<html xmlns=\"http://www.w3.org/1999/xhtml \">\n" +
                " <head>\n" +
                "  <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n" +
                "  <meta name=\"Generator\" content=\"EditPlus®\"/>\n" +
                "  <meta name=\"Author\" content=\"\"/>\n" +
                "  <meta name=\"Keywords\" content=\"\"/>\n" +
                "  <meta name=\"Description\" content=\"\"/>\n" +
                "  <title>Document</title>\n" +
                "\n" +
                "\n" +
                "<style type=\"text/css\">\n" +
                "body {\n" +
                "      p{line-height:30px}\n" +
                "}\n" +
                "::v-deep h5, .h5 {\n" +
                " font-size: 14px;\n" +
                "}\n" +
                "\n" +
                "::v-deep h4, .h4 {\n" +
                " font-size: 16px;\n" +
                " font-weight: bold;\n" +
                "}\n" +
                "\n" +
                "::v-deep h3, .h3 {\n" +
                " font-size: 18px;\n" +
                " font-weight: bold;\n" +
                "}\n" +
                "\n" +
                "::v-deep h2, .h2 {\n" +
                " font-size: 20px;\n" +
                " font-weight: bold;\n" +
                "}\n" +
                "\n" +
                "::v-deep h1, .h1 {\n" +
                " font-size: 22px;\n" +
                " font-weight: bold;\n" +
                "}\n" +
                "::v-deep i {\n" +
                " font-style: italic\n" +
                "}\n" +
                "::v-deep .w-e-toolbar .w-e-menu i {\n" +
                " font-style: normal;\n" +
                "}\n" +
                "::v-deep ol {\n" +
                " list-style-type: decimal;\n" +
                "}\n" +
                "font[size=\"1\"] {\n" +
                " font-size: 12px;\n" +
                "}\n" +
                "font[size=\"2\"] {\n" +
                " font-size: 14px;\n" +
                "}\n" +
                "font[size=\"3\"] {\n" +
                " font-size: 16px;\n" +
                "}\n" +
                "font[size=\"4\"] {\n" +
                " font-size: 18px;\n" +
                "}\n" +
                "font[size=\"5\"] {\n" +
                " font-size: 24px;\n" +
                "}\n" +
                "font[size=\"6\"] {\n" +
                " font-size: 32px;\n" +
                "}\n" +
                "font[size=\"7\"] {\n" +
                " font-size: 48px;\n" +
                "}\n" +
                "/* blockquote 样式 */\n" +
                "::v-deep blockquote {\n" +
                " display: block;\n" +
                " border-left: 8px solid #d0e5f2;\n" +
                " padding: 5px 10px;\n" +
                " margin: 10px 0;\n" +
                " line-height: 1.4;\n" +
                " min-height: 24px;\n" +
                " font-size: 100%;\n" +
                " background-color: #f1f1f1;\n" +
                "}\n" +
                "/* table 样式 */\n" +
                "/* table 样式 */\n" +
                "::v-deep table {\n" +
                " border-top: 1px solid #ccc;\n" +
                " border-left: 1px solid #ccc;\n" +
                "}\n" +
                "::v-deep table td,\n" +
                "::v-deep table th {\n" +
                " border-bottom: 1px solid #ccc;\n" +
                " border-right: 1px solid #ccc;\n" +
                " padding: 3px 5px;\n" +
                " height:32px;\n" +
                "}\n" +
                "::v-deep table th {\n" +
                " border-bottom: 2px solid #ccc;\n" +
                " text-align: center;\n" +
                " background-color: #f1f1f1 ;\n" +
                "}\n" +
                "</style>\n" +
                " </head>\n" +
                " <body style=\"line-height: 30px\">";
        content.replace("<html>",replace1);
        content.replace("</html>","</body></html>");
  1. 接下来是相关的工具

主要工具代码



UploadFileDTO 我们自己封装的文件返回类,自己换自己的
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.codec.Base64;
import com.itextpdf.tool.xml.XMLWorker;
import com.itextpdf.tool.xml.XMLWorkerFontProvider;
import com.itextpdf.tool.xml.css.StyleAttrCSSResolver;
import com.itextpdf.tool.xml.html.CssAppliers;
import com.itextpdf.tool.xml.html.CssAppliersImpl;
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 lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.*;
import java.nio.charset.Charset;

@Component
@Slf4j
public class ContractPdfUtil {

    @Resource
    private FileUtil fileUtil;
//TODO 我们自己封装文件上传工具,自己用自己的
    @Resource
    private FileService fileService;

    //    生成hellowlod
    public void hellowPdf() throws IOException, DocumentException {
        Document document = new Document(PageSize.A4);
        //第二步,创建Writer实例
        PdfWriter.getInstance(document, new FileOutputStream("hello.pdf"));
        //创建中文字体
        BaseFont bfchinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
        Font fontChinese = new Font(bfchinese, 12, Font.NORMAL);
        //第三步,打开文档
        document.open();
        //第四步,写入内容
        Paragraph paragraph = new Paragraph("hello world", fontChinese);
        document.add(paragraph);
        //第五步,关闭文档
        document.close();
    }

//    ----------------------讲html生成pdf---------------------------------
    /**
     * 创建PDF文件
     * @param htmlStr
     * @throws Exception
     */
    public   UploadFileDTO writeToOutputStreamAsPDF(Integer companyId,String name,String htmlStr) throws Exception {
//        String targetFile = "pdfDemo1.pdf";
//        File targeFile = new File(targetFile);
//        if(targeFile.exists()) {
//            targeFile.delete();
//        }
        String filePath = null;
        String fileName = "合同"+System.currentTimeMillis() + ".pdf";
        try {
            filePath = fileUtil.newfilePath(fileName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //定义pdf文件尺寸,采用A4横切
        Document document = new Document(PageSize.A4, 70, 70, 40, 50);// 左、右、上、下间距
        //定义输出路径
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filePath));
        PdfReportM1HeaderFooter header = new PdfReportM1HeaderFooter("", 8, PageSize.A4);
        writer.setPageEvent(header);
        writer.addViewerPreference(PdfName.PRINTSCALING, PdfName.NONE);
        document.open();

        // CSS
        CSSResolver cssResolver = new StyleAttrCSSResolver();
        CssAppliers cssAppliers = new CssAppliersImpl(new XMLWorkerFontProvider(){

            @Override
            public Font getFont(String fontname, String encoding, boolean embedded, float size, int style, BaseColor color) {
                try {
                    //用于中文显示的Provider
                    BaseFont bfChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
                    log.error("bfChinese == > {}",bfChinese ==null);
                    return new Font(bfChinese, size, style);
                } catch (Exception e) {
                    log.error("getFont ",e);
                    return super.getFont(fontname, encoding, size, style);
                }
            }
        });

        //html
        HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers);
        htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
        htmlContext.setImageProvider(new 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 if (src.startsWith("http")) {
                        return Image.getInstance(src);
                    }
                } catch (BadElementException ex) {
                    return null;
                } catch (IOException ex) {
                    return null;
                }
                return null;
            }

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


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

        // XML Worker
            final Charset charset = Charset.forName("UTF-8");
        XMLWorker worker = new XMLWorker(css, true);
        XMLParser p = new XMLParser(true ,worker,charset);
        try {
            p.parse(new ByteArrayInputStream(htmlStr.getBytes("UTF-8")),charset);
        }
        catch (Exception e)
        {
            e.getMessage();
        }

        document.close();
        UploadFileDTO uploadFileDTO = fileService.fileUploadBytes(FileUtils.readFileToByteArray(new File(filePath)), companyId + "/contract/order/" + fileName);
return uploadFileDTO;
    }

    /**
     * 读取 HTML 文件
     * @return
     */
    private static String readHtmlFile() {
        StringBuffer textHtml = new StringBuffer();
        try {
            File file = new File("D:\\test.html");
            BufferedReader reader = new BufferedReader(new FileReader(file));
            String tempString = null;
            // 一次读入一行,直到读入null为文件结束
            while ((tempString = reader.readLine()) != null) {
                textHtml.append(tempString);
            }
            reader.close();
        } catch (IOException e) {
            System.out.println("e"+e.toString());
            return null;
        }
        return textHtml.toString();
    }



    public static void main(String[] args) throws Exception {
 

    }
}

接下来是页眉页脚样式啥的支持类



import java.io.IOException;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfTemplate;
import com.itextpdf.text.pdf.PdfWriter;

public class PdfReportM1HeaderFooter 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;

    /**
     *
     * Creates a new instance of PdfReportM1HeaderFooter 无参构造方法.
     *
     */
    public PdfReportM1HeaderFooter() {

    }

    /**
     *
     * Creates a new instance of PdfReportM1HeaderFooter 构造方法.
     *
     * @param yeMei
     *            页眉字符串
     * @param presentFontSize
     *            数据体字体大小
     * @param pageSize
     *            页面文档大小,A4,A5,A6横转翻转等Rectangle对象
     */
    public PdfReportM1HeaderFooter(String yeMei, int presentFontSize, Rectangle pageSize) {
        this.header = yeMei;
        this.presentFontSize = presentFontSize;
        this.pageSize = pageSize;
    }

    public void setHeader(String header) {
        this.header = header;
    }

    public void setPresentFontSize(int presentFontSize) {
        this.presentFontSize = presentFontSize;
    }

    /**
     *
     * TODO 文档打开时创建模板
     *
     * @see PdfPageEventHelper#onOpenDocument(PdfWriter, Document)
     */
    public void onOpenDocument(PdfWriter writer, Document document) {
        total = writer.getDirectContent().createTemplate(50, 50);// 共 页 的矩形的长宽高
    }

    /**
     *
     * TODO 关闭每页的时候,写入页眉,写入'第几页共'这几个字。
     *
     * @see PdfPageEventHelper#onEndPage(PdfWriter, Document)
     */
    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();

        //自己增加的
        /*
        if(pageS==1){
            Phrase footerLeft = new Phrase("978-1-4799-0530-031.00 ©2013 IEEE", fontDetail);
            ColumnText.showTextAligned(cb, Element.ALIGN_LEFT, footerLeft, document.left(), document.bottom() - 20, 0);
        }
*/

        // 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() - 20, 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() - 20); // 调节模版显示的位置

    }

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

4到这就完成了,测试一下

UploadFileDTO uploadFileDTO = new UploadFileDTO() ;

try {

uploadFileDTO = contractPdfUtil.writeToOutputStreamAsPDF(ro.getCompanyId(), templateEmailDTO.getSubject(), templateEmailDTO.getContent());

} catch (Exception exception) {

exception.printStackTrace();

}

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
你可以使用JavaiText 库来实现富文本生成PDF并进行下载。以下是一个简单的示例代码: ```java import com.itextpdf.text.Document; import com.itextpdf.text.DocumentException; import com.itextpdf.text.Paragraph; import com.itextpdf.text.Font; import com.itextpdf.text.pdf.BaseFont; import com.itextpdf.text.pdf.PdfWriter; import java.io.FileOutputStream; import java.io.IOException; public class RichTextToPdf { public static void main(String[] args) { String richText = "<h1>标题</h1><p>这是一个示例富文本。</p><ul><li>列表项1</li><li>列表项2</li></ul>"; Document document = new Document(); try { PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("output.pdf")); document.open(); // 设置字体 BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); Font font = new Font(bfChinese, 12, Font.NORMAL); // 添加富文本内容到PDF Paragraph paragraph = new Paragraph(); paragraph.setFont(font); paragraph.setLeading(20); paragraph.setMultipliedLeading(1); paragraph.setIndentationLeft(20); paragraph.setIndentationRight(20); paragraph.setFirstLineIndent(-20); paragraph.add(richText); document.add(paragraph); document.close(); writer.close(); System.out.println("PDF生成成功!"); } catch (DocumentException | IOException e) { e.printStackTrace(); } } } ``` 上述代码会生成一个名为 `output.pdf` 的PDF文件,其中包含了示例的富文本内容。你可以根据需要修改字体、样式、布局等参数来适应你的具体需求。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值