实现Word转Pdf文件

在项目中需要以Word文件为模板,填充指定数据,并转换为Pdf文件。可以分为两步,第一步使用POI进行文本替换,第二步把替换后的Word转换为pdf文件。

当前遇到的问题是网上所有的转换工具依赖的包都过大,一般要30M以上。而自己通过Poi实现转换的成本又太高,且转换效果不够理想。最终尝试一下,先从Word转换为HTML,然后再从HTML转换为pdf。

虽然转换成功了,但是由于在从word转换给html时使用了ooxml-schema.jar包,此包有十几兆,总依赖仍旧超过30M。最终放弃了此方法。当过程值得记录下来,以供以后参考。

1.Word转换为html

除了poi相关包(我当前使用的4.1.2版本)以外,还需要ooxml-schemas.jar和xdocreport.jar,依赖配置如下:

            
                org.apache.poi
                ooxml-schemas
                1.4
            
            
                fr.opensagres.xdocreport
                xdocreport
                2.0.2
            

代码实现及注释如下:

 /**
     * docx文件转html
     * 参考: https://wooaooo.com/2022/02/12/Java/POI/java-poi5.2.0-word-to-html/
     * @param wordInput word文件输入流。
     * @param  data 需要填充的数据。
     */
    public static String word2007ToHtml(InputStream wordInput, Map data)
            throws IOException {

        // 加载word文档生成 XWPFDocument对象
        XWPFDocument document = new XWPFDocument(wordInput);

        //  带图片的word,则将图片转为base64编码,保存在一个页面中
        XHTMLOptions options = XHTMLOptions.create().indent(3).setImageManager(new Base64EmbedImgManager());
        //若设置true,表示外层没有html\head\body标签,设为false,保留html等标签。
        options.setFragment(true);
        //转换为html
        StringWriter writer = new StringWriter();
        XHTMLConverter xhtmlConverter = (XHTMLConverter) XHTMLConverter.getInstance();
        xhtmlConverter.convert(document, writer, options);
        String html = writer.toString();
        // 解析html并优化布局
        Document doc = Jsoup.parseBodyFragment(html);
        //去掉页边距和固定宽度
        Elements elements = doc.getElementsByTag("div");
        for(Element element : elements){
            element.attr("style","line-height:2em;margin-left: 3em; margin-right: 3em;");
        }
        //设置所有table的样式
        Elements tables = doc.getElementsByTag("table");
        for (Element table : tables) {
            table.attr("style", "border-collapse: collapse;");
        }
        //文本替换。
        html = doc.outerHtml();
        for(Map.Entry item : data.entrySet()){
            html = html.replace(item.getKey(),item.getValue());
        }
        return html;
    }

2.html转换为pdf

需要用到的jar包配置如下:

            
                com.itextpdf
                itext7-core
                ${itextpdf.version}
                pom
            
            
                com.itextpdf
                font-asian
                ${itextpdf.version}
            
            
                com.itextpdf
                html2pdf
                3.0.3
            

代码实现及注释如下:

    /**
     * html转换为pdf
     * @param html html文本内容
     * @param output pdf文件输出
     */
    public static void htmlToPdf(String html, OutputStream output) throws IOException {
        //转换时参数配置,例如字体,依赖图片等文件路径
        ConverterProperties properties = new ConverterProperties();
        //必须设置字体,否则转换的pdf文件不显示汉字
        FontProvider fp = new FontProvider();
        fp.addFont(FontProgramFactory.createFont("STSong-Light"),"UniGB-UCS2-H");
        properties.setFontProvider(fp);
        //转换
        try(PdfDocument pdfDocument = new PdfDocument(new PdfWriter(output))){
            //设置pdf页面大小为A4
            pdfDocument.setDefaultPageSize(PageSize.A4);
            HtmlConverter.convertToPdf(html,pdfDocument,properties);
        }
    }

3.其他实现word转换pdf的方法

其他实现word转换为pdf的方法可以参考:Java开发中Word转PDF文件5种方案横向评测,我最终选择的是aspose-words,因为其转换效果比较好,依赖包相对比较小,且代码量少。

放弃了通过html转换pdf后,就可以直接通过Word转换为pdf了。需要通过poi-tl.jar来实现word中的数据替换,然后再通过aspose-words.jar转换为pdf。依赖包如下:

    
      org.apache.poi
      poi
      4.1.2
      compile
    
    
      org.apache.poi
      poi-ooxml
      4.1.2
      compile
    
    
      org.apache.poi
      poi-ooxml-schemas
      4.1.2
      compile
    
    
      com.deepoove
      poi-tl
      1.10.5
    
    
      com.luhuiguo
      aspose-words
      23.1
    

代码实现相当简单,如下:

package com.zhengzhaoxi.web.common;

import com.aspose.words.Document;
import com.aspose.words.PdfSaveOptions;
import com.deepoove.poi.XWPFTemplate;

import java.io.*;
import java.util.Map;

/**
 * Word工具类
 * @author donghx
 * @author 2023-06-14
 */
public class WordUtils {

    /**
     * 填充数据
     * @param input 输入word文件数据流
     * @param data 需要替换的数据映射
     * @param output 输出的word文件数据量
     * @throws IOException
     */
    public static void fillData(InputStream input, Map data, OutputStream output) throws IOException {
        //使用poi-tl.jar中的类填充数据
        try(XWPFTemplate template = XWPFTemplate.compile(input) ){
            template.render(data).writeAndClose(output);
        }catch (Exception ex){
            throw ex;
        }
    }

    /**
     * word转换为pdf
     * @param wordInput word文件输入流
     * @param pdfOutput pdf文件输出流
     * @throws Exception
     */
    public static void wordToPdf(InputStream wordInput, OutputStream pdfOutput) throws Exception {
        //通过aspose-words.jar中的类转换文件
        Document wordDoc = new Document(wordInput);
        PdfSaveOptions pso = new PdfSaveOptions();
        wordDoc.save(pdfOutput, pso);
    }
}

你可能感兴趣的:(java,word,pdf,java)