这可能是目前最全的word转pdf的一些方法总结

濮丁雷
2023-12-01

word转pdf是一个比较老的话题了,网上有各种各样的版本,经过了各种尝试,主要是在linux和windows平台运行,有通过脚本的,有通过代码的,这些方法效果各异。

一、openoffice和libreoffice
这两个是开源软件,libreoffice是openoffice的一个分支,两个软件的表现,只能说是中规中矩,如果样式不是很多,且对样式没有很高的要求,还是基本满足要求的。它们两个在word转pdf的时候,一些样式是和Microsoft office是不兼容的,还有一些计算公式也要小心使用(比如一些页眉和页脚的计算)。

libreoffice的安装:安装过程
openoffice的安装和使用:openoffice安装使用

openoffice的临时启动:
/opt/openoffice4/program/soffice -headless -accept=”socket,host=127.0.0.1,port=8100;urp;” -nofirststartwizard

openoffice的永久启动:
nohup /opt/openoffice4/program/soffice -headless -accept=”socket,host=127.0.0.1,port=8100;urp;” -nofirststartwizard &

然后查看是否启动完成:ps -ef|grep openoffice
查看默认端口8100:netstat -lnp |grep 8100

解决中文乱码问题:解决中文乱码
主要思路:乱码的主要原因是字体的不识别,所以将windows的字体拷贝到linux

word转pdf的思路,有两条:1、将linux命令写入到代码中 2、用代码启动openoffice服务进行转换

1、命令方式:参考链接:DocumentConvert.py+Openoffice方式
2、代码方式,参考链接:java+OpenOffice+JodConverter方式

二、Apache的wordConverterToPdf方式进行转换
这种方式的转换,比较麻烦,而且样式的支持不好。

package pageOffice.utils;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections4.MapUtils;
import org.apache.poi.xwpf.converter.core.utils.StringUtils;
import org.apache.poi.xwpf.converter.pdf.PdfConverter;
import org.apache.poi.xwpf.converter.pdf.PdfOptions;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;

public class WordPdfUtils {

    public static void main(String[] args) throws Exception {
        // String filepath = "xxxx.docx";
        String filepath = "xxxx.doc";
        String outpath = "xxxx.pdf";

        InputStream source = new FileInputStream(filepath);
        OutputStream target = new FileOutputStream(outpath);
        Map<String, String> params = new HashMap<String, String>();

        PdfOptions options = PdfOptions.create();

        wordConverterToPdf(source, target, options, params);
    }

    /**
     * 将word文档, 转换成pdf, 中间替换掉变量
     * 
     * @param source
     *            源为word文档, 必须为docx文档
     * @param target
     *            目标输出
     * @param params
     *            需要替换的变量
     * @throws Exception
     */
    public static void wordConverterToPdf(InputStream source, OutputStream target, Map<String, String> params)
            throws Exception {
        wordConverterToPdf(source, target, null, params);
    }

    /**
     * 将word文档, 转换成pdf, 中间替换掉变量
     * 
     * @param source
     *            源为word文档, 必须为docx文档
     * @param target
     *            目标输出
     * @param params
     *            需要替换的变量
     * @param options
     *            PdfOptions.create().fontEncoding( "windows-1250" ) 或者其他
     * @throws Exception
     */
    public static void wordConverterToPdf(InputStream source, OutputStream target, PdfOptions options,
            Map<String, String> params) throws Exception {
        XWPFDocument doc = new XWPFDocument(source);
        paragraphReplace(doc.getParagraphs(), params);
        for (XWPFTable table : doc.getTables()) {
            for (XWPFTableRow row : table.getRows()) {
                for (XWPFTableCell cell : row.getTableCells()) {
                    paragraphReplace(cell.getParagraphs(), params);
                }
            }
        }
        PdfConverter.getInstance().convert(doc, target, options);
    }

    /** 替换段落中内容 */
    private static void paragraphReplace(List<XWPFParagraph> paragraphs, Map<String, String> params) {
        if (MapUtils.isNotEmpty(params)) {
            for (XWPFParagraph p : paragraphs) {
                for (XWPFRun r : p.getRuns()) {
                    String content = r.getText(r.getTextPosition());
                    if (StringUtils.isNotEmpty(content) && params.containsKey(content)) {
                        r.setText(params.get(content), 0);
                    }
                }
            }
        }
    }

}

三、SaveAsPDFandXPS + jacob.jar + jacob.dll
效果最好的一种方法,但是需要 window 环境,而且速度是最慢的需要安装 msofficeWord 以及 SaveAsPDFandXPS.exe,这种方式目前还没有找到能够在linux上运行的版本
代码如下:

import java.io.File;

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;

/**
 * 效果最好的一种方法,但是需要 window 环境,而且速度是最慢的需要安装 msofficeWord 以及 SaveAsPDFandXPS.exe (
 * word 的一个插件,用来把 word 转化为 pdf,可以不用安装,本次未安装测试通过 )
 * 
 * SaveAsPDFandXPS
 * 下载地址:http://www.microsoft.com/zh-cn/download/details.aspx?id=7 
 * jacob 包下载地址:http://sourceforge.net/projects/jacob-project/
 * 
 * jacob.jar 放在 E:\jdk1.5.0_14\jre\lib\ext 
 * jacob.dll 放在 E:\jdk1.5.0_14\jre\bin
 * 
 * @author u Y
 *
 */
public class WordToPdf {

    private static final int wdFormatPDF = 17; // PDF 格式

    public void wordToPDF(String sfileName, String toFileName) {

        System.out.println("启动 Word...");
        long start = System.currentTimeMillis();
        ActiveXComponent app = null;
        Dispatch doc = null;
        try {
            app = new ActiveXComponent("Word.Application");
            app.setProperty("Visible", new Variant(false));
            Dispatch docs = app.getProperty("Documents").toDispatch();
            doc = Dispatch.call(docs, "Open", sfileName).toDispatch();
            System.out.println("打开文档..." + sfileName);
            System.out.println("转换文档到 PDF..." + toFileName);
            File tofile = new File(toFileName);
            if (tofile.exists()) {
                tofile.delete();
            }
            Dispatch.call(doc, "SaveAs", toFileName, // FileName
                    wdFormatPDF);
            long end = System.currentTimeMillis();
            System.out.println("转换完成..用时:" + (end - start) + "ms.");

        } catch (Exception e) {
            System.out.println("========Error:文档转换失败:" + e.getMessage());
        } finally {
            Dispatch.call(doc, "Close", false);
            System.out.println("关闭文档");
            if (app != null)
                app.invoke("Quit", new Variant[] {});
        }
        // 如果没有这句话,winword.exe进程将不会关闭
        ComThread.Release();
    }

    public static void main(String[] args) {
        WordToPdf d = new WordToPdf();
        d.wordToPDF("E://test.doc", "E://test.pdf");
    }

}

四:AsposeWord方式

该方式是重点推出的方式,效果好,而且跨平台,但是不是开源的,但网上也有一些绿色版本,大家在选择版本的时候,可以先试用,看看效果,然后再选择相应的版本,因为最新的版本可能不稳定,在测试过程中,最新版本转换pdf的时候出现空指针错误,有可能是新版本对样式的转换出现问题,目前比较好的版本是17开头的。

试用版和正式版的最大区别就是:试用版会有水印,而正式版没有

代码很简单的几行:

package pageOffice.utils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;


import com.aspose.words.Document;
import com.aspose.words.License;
import com.aspose.words.SaveFormat;


/**
 * @author Administrator
 * @version $Id$
 * @since
 * @see
 */
public class Word2PdfUtil {

    public static void main(String[] args) {
        doc2pdf("E:/test.doc","E:/ttt.pdf");
    }

    public static boolean getLicense() {
        boolean result = false;
        try {
            File file = new File("E:\\license.xml"); // 新建一个空白pdf文档
            InputStream is = new FileInputStream(file); // license.xml应放在..\WebRoot\WEB-INF\classes路径下
            License aposeLic = new License();
            aposeLic.setLicense(is);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public static void doc2pdf(String inPath, String outPath) {
        if (!getLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生
            return;
        }
        try {
            long old = System.currentTimeMillis();
            File file = new File(outPath); // 新建一个空白pdf文档
            FileOutputStream os = new FileOutputStream(file);
            Document doc = new Document(inPath); // Address是将要被转化的word文档
            doc.save(os, SaveFormat.PDF);// 全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF,
                                         // EPUB, XPS, SWF 相互转换
            long now = System.currentTimeMillis();
            System.out.println("共耗时:" + ((now - old) / 1000.0) + "秒"); // 转化用时
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

license.xml的下载:license.xml
jar包的下载:aspose-words-15.8.0.jar

没有积分的童鞋可以留邮箱私发哦~

五、采用第三方技术 IText、Poi、Jsoup

该方法的思路是,先将word转换成html,然后再将html转换为pdf,先不说该思路实现起来麻烦,有点曲线救国的意思,但是难以掌控的是样式的转换,转换了两次还能够保持一样吗,上面那些方法都是转换一次,都很难保证一致,更不用说这个转换两次的了,所以不太看好。

参考链接:采用第三方技术 IText、Poi、Jsoup

写到这里,相信很多人也明白了,最好的两种方式是第三种和第四种,尤其是Aspose-word,可以跨平台,但它是商用软件。一开始被看好的开源的office,在一些普通的样式里面是够用了,但是一些复杂的样式,与Microsoft office的样式不兼容的时候,会出现转换的差异,尤其是对不同的编辑软件的兼容性也很不好,比如用Microsoft office和WPS编辑之后,转换出来的结果也不一样。要求不是特别高的,还是可以尝试此方案的。如果有windows服务器,可以将第三种方式:SaveAsPDFandXPS + jacob.jar + jacob.dll 做成工具包,提供给其他服务器进行调用,这样也是可以的。

完成这个功能的时候,走了特别多的弯路,希望在看这篇文章的你,能够结合这篇文章少走一些弯路。

 类似资料: