Windows和Linux平台上实现Word转PDF

前言

调研后发现网上有很多解决办法,Windows平台上word和PDF可以完美的转换,但大部分业务是要求在Linux上运行的,基于Windows的方法无法移植到Linux上运行,现有的Linux上的Word文档转换为PDF的方法验证后大多数存在PDF和Word格式不一致的问题(比如PDF与Word排版页数不一致,文字排列更紧凑等),所以本文的主要目标是解决Linux平台上Word转为PDF之后的格式版面不一致的问题,先放结论,对于大部分测试用例文档格式在转换后基本一致,存在少部分不一致的问题。并且将java项目打包成jar包并在linux平台上调用命令行测试通过。

Windows平台Word转PDF

import win32com  # python -m pip install pypiwin32
from win32com.client import Dispatch
import sys

def word2pdf(file_path='/documents/4-科园商务会议服务协议_20191105广州.doc'):
	word = Dispatch('Word.Application')
	word.Visible = 0 # 后台运行,不显示
	word.DisplayAlerts = 0  #不警告
	path = sys.path[0] + file_path
	doc = word.Documents.Open(FileName=path, Encoding='gbk')
	doc.SaveAs(path[:-5]+'_pdfed.pdf', 17) #  txt=4, html=10, docx=16, pdf=17
	doc.Close()
	word.Quit()
	print("Word2Pdf 转换完成,PDF文件和Word在同级目录中。")

if __name__ == '__main__':
	# word2pdf('/documents/1-技术服务合同.docx')
	file_path = sys.argv[1]
	print(file_path)
	word2pdf(file_path)

win32com只能在windows平台上运行,linux上没有类似的依赖包。

Linux平台Word转PDF

1.基于unoconv工具实现word转为PDF
安装:yum install unoconv
使用:unoconv -f pdf XXX.docx

2.使用cups-pdf工具实现word转PDF
安装:sudo apt-get install cups-pdf
使用:oowriter -convert-to pdf:writer_pdf_Export XXX.docx

3.使用libreoffice测试:
soffice --headless --invisible --convert-to pdf XXX.docx

4.使用apose-words-15.8.0工具hacked(pojie)版,java编程实现word转PDF。(推荐,目前验证该方法Word转为PDF后格式变化最小)

Eclipse项目目录结构:(文末有完整项目源代码和打包的jar包,jar包测试可以直接调用)
在这里插入图片描述

【出现的问题记录】打成jar包后只能把jar包和待转换的word文档放在同一个目录下,并且生成的目录也只能放在同一个目录下,这和Java中getResourceAsStream的用法有关系:

getResourceAsStream读取的文件路径只局限与工程的源文件夹中,包括在工程src根目录下,以及类包里面任何位置,但是如果配置文件路径是在除了源文件夹之外的其他文件夹中时,该方法是用不了的。
引用自:https://www.iteye.com/blog/riddickbryant-436693

【已解决,封装jar包后读取项目目录外的文件】
之前打开word的文件的方法是利用getResourceAsStream:
file_path = "C:\\Users\\16616\\Desktop\\XXX.docx";
word = TestWord.class.getClassLoader().getResourceAsStream(file_path);
Document doc = new Document(word);
现在直接用new Document打开:
Document doc = new Document(file_path);

最后是源代码:

package com.demo;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.stream.Stream;

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

/**
 * 
 * 由于ASPOSE比较吃内存,操作大一点的文件就会堆溢出,所以请先设置好java虚拟机参数:-Xms512m -Xmx512m(参考值)<br>
 * 如有疑问,请在CSDN下载界面留言,或者联系QQ569925980<br>
 * 
 * @author Spark
 *
 */
public class TestWord {

    private static InputStream license;
    private static InputStream word;

    /**
     * 获取license
     * 
     * @return
     */
    public static boolean getLicense() {
        boolean result = false;
        try {
            license = TestWord.class.getClassLoader().getResourceAsStream("license.xml");// license路径
//            word = TestWord.class.getClassLoader().getResourceAsStream("\\4-广州.doc");
            License aposeLic = new License();
            aposeLic.setLicense(license);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
    
    public static void word2pdf(String file_path,String save_path) {
//    	word = TestWord.class.getClassLoader().getResourceAsStream("\\XXX.doc");// 原始word路径
    	word = TestWord.class.getClassLoader().getResourceAsStream(file_path);
    	
    	// 验证License
        if (!getLicense()) {
            return;
        }

        try {
            long old = System.currentTimeMillis();
//            Document doc = new Document(word);
            Document doc = new Document(file_path);
//            File file = new File("C:\\Users\\16616\\Desktop\\AsposeWord\\src\\test.pdf");// 输出路径
            
            //存为新PDF文件,文件名需要从file_path中提取出来
            File tempFile =new File(file_path.trim());
            String fileName = tempFile.getName();
            System.out.println("fileName = " + fileName);
            
            String[] tmp = fileName.split("\\.");
            String pdf_name = tmp[0]+".pdf";
            
            System.out.println("pdfName = "+ pdf_name);
            
            File file = new File(save_path+"/"+pdf_name);
            FileOutputStream fileOS = new FileOutputStream(file);
            
            doc.save(fileOS, SaveFormat.PDF);

            long now = System.currentTimeMillis();
            System.out.println("共耗时:" + ((now - old) / 1000.0) + "秒\n\n" + "文件保存在:" + file.getPath());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 
     * @param args
     */
    public static void main(String[] args) {
    	String file_path = args[0];
    	String save_path = args[1];
    	word2pdf(file_path,save_path);
    	
//    	word2pdf("C:\\Users\\16616\\Desktop\\XXX.docx","C:/Users/16616/Desktop");

    }
}

将含有第三方jar包的Java项目打包,并且使用命令行进行jar包的传参调用:
1.首先,Eclipse将已经含有第三方jar包的项目打包的方法:
File/Export…然后Java/Runnable JAR file,然后选要运行的有main()的类,选extract required libraries into generated JAR
在这里插入图片描述在这里插入图片描述

2.找到打包后的文件,将待转换的word文件放到jar包的同级目录下,如果想要将转换后的PDF文件放到word文件的同级:

命令行调用jar包方法:
java -jar word2pdf.jar [路径下的word文件名][PDF目标路径]
在这里插入图片描述最后会在该文件夹下生成一个pdfed.pdf文件。

:如何命令行传参调用java项目(或在bat文件中调用)

  1、无参
   打开jar包所在目录,输入 java -jar xxx.jar
  2、有参
  打开jar包所在目录   输入  java -jar xxx.jar 参数1 参数2 ……(参数间用空格隔开)
  对应main函数中的:
	public static void main(String[] args) {	    
	    String sourcePath = args[0];// 参数1 
	    String targetPath = args[1];// 参数2 
	}

项目的源代码jar包以及使用方法已经放在了公众号下,后台回复关键词【word2pdf】即可获取。

在这里插入图片描述

参考文献

[1] how-to-convert-word-doc-to-pdf-in-linux
[2] 将java项目导出为jar包+导出第三方jar包+使用命令行调用+传参
[3] aspose-words-15.8.0 完美解决word转pdf
[4] 怎样把引用的jar包和本项目一起导出成jar文件

Logo

更多推荐