参考了里面的libreoffice的用法:https://blog.youkuaiyun.com/qwert678000/article/details/72770109
需求描述
最近在做word报表的自动生成,甲方要求要有pdf格式,且对样式要求特别严格。
上网搜了很多,发现在对word样式要求特别高的情况下,用libreoffice是特别好的选择。
基本上几秒钟10多页就出来。如果对样式要求不高,可以尝试其他的方法(aspose是个很好用的word->pdf的库)。
步骤
1.安装libreoffice(linux还需要装unoconv),windows到官网下载安装包,linux直接用命令行装即可:
https://zh-cn.libreoffice.org/get-help/install-howto/linux/(linux版及libreoffice中文官网)
2.验证安装是否成功
黑窗口直接敲命令,windows下:soffice --convert-to pdf example.docx
linux下: doc2pdf example.docx, windows需要添加path系统变量(C:\Program Files\LibreOffice 5\program),不然无法识别soffice命令
3.写代码:
WordPdfUtils类:Word转Pdf主类
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;
import org.apache.commons.collections4.MapUtils;
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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.opensagres.xdocreport.utils.StringUtils;
/**
* @author Rocca
*
*/
public class WordPdfUtils {
protected static final Logger logger = LoggerFactory.getLogger(WordPdfUtils.class);
public boolean wordConverterToPdf(String docxPath) throws IOException {
File file = new File(docxPath);
String path = file.getParent();
try {
String osName = System.getProperty("os.name");
String command = "";
if (osName.contains("Windows")) {
//soffice --convert-to pdf -outdir E:/test.docx
command = "soffice --convert-to pdf -outdir " + path + " " + docxPath;
} else {
command = "doc2pdf --output=" + path + File.separator + file.getName().replaceAll(".(?i)docx", ".pdf") + " " + docxPath;
}
String result = CommandExecute.executeCommand(command);
// LOGGER.info("result==" + result);
System.out.println("生成pdf的result==" + result);
if (result.equals("") || result.contains("writer_pdf_Export")) {
return true;
}
} catch (Exception e) {
e.printStackTrace();
throw e;
}
return false;
}
//测试用
public static void main(String[] args) {
try {
// 建议都用/左斜杠这种,左斜杠是windows和linux通用的
new WordPdfUtils().wordConverterToPdf("E:/test.docx");
} catch (IOException e) {
System.out.println("word转换成pdf时出错");
e.printStackTrace();
}
}
}
CommandExecute类:执行linux或windows命令行
package com.bupt.nctc.utils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.apache.commons.io.IOUtils;
/**
* linux或windows命令执行
*/
public class CommandExecute {
// public static void main(String[] args) {
// CommandExecute obj = new CommandExecute();
// String domainName = "www.baidu.com";
// //in mac oxs
// String command = "ping " + domainName;
// //in windows
// //String command = "ping -n 3 " + domainName;
// String output = obj.executeCommand(command);
// System.out.println(output);
// }
public static String executeCommand(String command) {
StringBuffer output = new StringBuffer();
Process p;
InputStreamReader inputStreamReader = null;
BufferedReader reader = null;
try {
p = Runtime.getRuntime().exec(command);
p.waitFor();
inputStreamReader = new InputStreamReader(p.getInputStream(), "UTF-8");
reader = new BufferedReader(inputStreamReader);
String line = "";
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
}
//p.destroy();//这个一般不需要
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(reader);
IOUtils.closeQuietly(inputStreamReader);
}
System.out.println(output.toString());
return output.toString();
}
}
备注:里面的main(0方法去掉注释后,可以用来做测试
4.解决中文乱码问题
复制windows的常用字体到linux下(常用字体如宋体、黑体)
可以先把字体文件夹复制到linux下的某个文件夹下,然后复制到目标位置:
如:sudo cp -r dir1 dir2
在我的电脑上是:sudo cp -r /home/nctc/fonts /usr/share/fonts就可以完成了。(试过2次都行)
上面是参考了这个https://blog.youkuaiyun.com/frylion/article/details/8207259把字体复制到/usr/share/fonts下。