以下有五种方法:
结论:
office不支持跨平台,
aspose收费,
基于pio+itext转换后会严重失真,
基于libreOffice不支持插入图形,否则会造成文本发生走样
而openOffice各种效果,效率……都是未测的。。。。
总结:目前仅考虑openOffice和libreOffice
openOffice实战原理:
通过第三方工具openOffice,将word、excel、ppt、txt等文件转换为pdf文件
先安装openOffice软件(Windows或Linux有提供软件)
使用JODConverter的Java的Opendocument 文件转换器API操作Office系列文件转换为PDF文件
优点:
转换效果比较好。是比较主流的做法
缺点:
服务器需要安装openOffice,比较负重。启动服务时效率不是很高
具体实现:
1.下载安装软件
1)Openoffice:Apache下的一个开放免费的文字处理软件
下载地址:Apache OpenOffice - 下载
2)JODConverter一个Java的Opendocument 文件转换器,只用到它的jar包
下载地址:JODConverter - Browse /JODConverter at SourceForge.net
安装openoffice
1.安装linux的openoffice
1.Apache OpenOffice - 下载 去官网链接下载linux版本的openOffice 以4.1.2 版本为例。
2.将压缩包上传至服务器上,并进行解压安装。
1 tar -zxvf 对应的压缩包名字 2 cd 进入解压后的 /zh-cn/RPMS 3 yum localinstall *.rpm 4 cd desktop-integration 5 rpm -ivh 含redhat的
默认会安装在/opt目录下会出现openoffice4。
3.启动服务
1 /opt/openoffice4/program/soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard 临时启动 2 nohup /opt/openoffice4/program/soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard & 后台启动
端口号根据自己项目实际来确定。
后台启动会一直占用内存,据各路大神说 大概100M,我自己没测过具体值不清楚。
有的程序是需要预先启动openOffice 服务的,有的则在代码里自己启动服务。
4.查看进程
netstat -lnp |grep 端口号
大概显示成这样就算启动完了。
`tcp 0 0 127.0.0.1:8100 0.0.0.0:* LISTEN 14362``/soffice``.bin`
2.安装window的openoffice
比linux的更简单,安装好后,只需要在C:Program Files (x86)OpenOffice 4program执行下面的命令就可以了
// soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststa
linux开机,重启openoffice服务(linux下openoffice启动和自动启动设置(centos)_resolute123的博客-CSDN博客_linux openoffice重启)
编辑vi /etc/rc.local
添加如下命令
soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard &
重启linux,命令reboot netstat -lnp |grep 8100 - - - 查看是否会出现以下信息,表示成功 tcp 0 0 127.0.0.1:8100 0.0.0.0:* LISTEN 8220/soffice.bin
2.Java实现
依赖
4.0.0 org.springframework.boot spring-boot-starter-parent2.5.4 com.officetopdf officetopdf0.0.1-SNAPSHOT officetopdf war Demo project for Spring Boot 1.8 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-testtest com.google.code.gson gson2.8.5 com.alibaba fastjson1.2.60 com.itextpdf itextpdf5.5.0 com.itextpdf itext-pdfa5.5.0 com.itextpdf itext-asian5.2.0 com.itextpdf.tool xmlworker5.5.0 org.jodconverter jodconverter-local4.1.0 org.xhtmlrenderer flying-saucer-pdf9.0.7 com.artofsolving jodconverter2.2.1 com.github.livesense jodconverter-core1.0.5 org.jodconverter jodconverter-core4.1.0 org.jodconverter jodconverter-local4.1.0 org.jodconverter jodconverter-spring-boot-starter4.1.0 org.libreoffice juh5.4.2 org.libreoffice jurt5.4.2 org.libreoffice ridl5.4.2 org.libreoffice unoil5.4.2 org.springframework spring-webmvc5.3.9 org.libreoffice officebean6.4.2 org.apache.httpcomponents httpclient commons-io commons-io2.11.0 javax.servlet jstlorg.apache.tomcat.embed tomcat-embed-jasperprovided org.springframework.boot spring-boot-starter-tomcatprovided javax.servlet javax.servlet-apiprovided org.apache.tomcat.embed tomcat-embed-jasperprovided org.springframework.boot spring-boot-maven-plugin
转换代码
package com.officetopdf.officetopdf.transform;
import java.io.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.google.gson.Gson;
import com.officetopdf.officetopdf.utils.HttpClientUtils;
import com.officetopdf.officetopdf.utils.ResultUtils;
import com.artofsolving.jodconverter.documentConverter;
import com.artofsolving.jodconverter.openoffice.connection.OpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.connection.SocketOpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.converter.StreamOpenOfficedocumentConverter;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
@ResponseBody
@RequestMapping("/start")
public class PDFDemo {
@RequestMapping("/topdf")
public static ResultUtils officeToPDF(@RequestBody Map map) {
String sourceFile = (String) map.get("sourceFile");//源文件,office
String targetFile = (String) map.get("targetFile");//pdf文件
String successCallback = (String) map.get("successCallback");//转换成功,回调的接口
String failCallback = (String) map.get("failCallback");//转换失败,回调的接口
String id = (String) map.get("id");
String token = (String) map.get("token");
try {
//对sourceFile,targetFile进行处理
File inputFile = new File(sourceFile);
if (!inputFile.exists()) { // 找不到源文件, 则返回false
return ResultUtils.error("找不到源文件");
}
File outputFile = new File(targetFile);
if (!outputFile.getParentFile().exists()) {//如果目标路径不存在,则创建
outputFile.getParentFile().mkdirs();
}
if (outputFile.exists()) {//如果目标文件存在,则删除
outputFile.delete();
}
new Thread(new Runnable() {
@Override
public void run() {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
OpenOfficeConnection connection = new SocketOpenOfficeConnection();
//如果在此处报错,可能需要启动openoffice服务
// windows启动命令
//cd C:Program Files (x86)OpenOffice 4program
//执行命令: soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststa
// linux启动命令
// /opt/openoffice4/program/soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard 临时启动
// nohup /opt/openoffice4/program/soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard & 后台启动
try {
connection.connect();
//用于测试openOffice连接时间
Date time1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(df.format(new Date()));
System.out.println("连接时间:" + time1);
documentConverter converter = new StreamOpenOfficedocumentConverter(
connection);
converter.convert(inputFile, outputFile);
//测试word转PDF的转换时间
Date time2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(df.format(new Date()));
System.out.println("转换时间:" + time2);
long time = time2.getTime() - time1.getTime();
System.out.println("totalTime:" + time + "ms");
connection.disconnect();
//转换成功返回的数据
PostEntity postEntity=new PostEntity();
postEntity.setId(id);
postEntity.setSuccessCallback(successCallback);
postEntity.setSourceFile(sourceFile);
postEntity.setTargetFile(targetFile);
postEntity.setToken(token);
HttpClientUtils.doPost(successCallback, new Gson().toJson(postEntity), token);
} catch (Exception e) {
e.printStackTrace();
System.err.println("openOffice连接失败!请检查IP,端口");
//转换失败返回的数据
Map params2 = new HashMap<>();
params2.put("id", id);
params2.put("sourceFile", sourceFile);
params2.put("targetFile", targetFile);
params2.put("token", token);
params2.put("failCallback", failCallback);
// HttpClientUtils.doPost(failCallback, params2, token);
}
}
}).start();
return ResultUtils.success("success");
} catch (Exception e) {
e.printStackTrace();
}
return ResultUtils.error("转换失败");
}
// @RequestMapping("/topdf2")
// public static ResultUtils officeToPDF2(@RequestBody Map map) {
// System.out.println(map);
// return ResultUtils.success("success");
// }
}
转换问题--不兼容docx和pptx
我这里使用的jodconverter是2.2.1的,不兼容docx和pptx,而jodconverter-2.2.2是兼容的。想要使用2.2.1版本,需要修改一下 BasicdocumentFormatRegistry 类中的 getFormatByFileExtension方法:
新建包 com.artofsolving.jodconverter 新建类BasicdocumentFormatRegistry,复制下面代码
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class BasicdocumentFormatRegistry implements documentFormatRegistry {
private List documentFormats = new ArrayList();
public BasicdocumentFormatRegistry() {
}
public void adddocumentFormat(documentFormat documentFormat) {
this.documentFormats.add(documentFormat);
}
protected List getdocumentFormats() {
return this.documentFormats;
}
public documentFormat getFormatByFileExtension(String extension) {
if (extension == null) {
return null;
} else {
if (extension.indexOf("doc") >= 0) {
extension = "doc";
}
if (extension.indexOf("ppt") >= 0) {
extension = "ppt";
}
if (extension.indexOf("xls") >= 0) {
extension = "xls";
}
String lowerExtension = extension.toLowerCase();
Iterator it = this.documentFormats.iterator();
documentFormat format;
do {
if (!it.hasNext()) {
return null;
}
format = (documentFormat)it.next();
} while(!format.getFileExtension().equals(lowerExtension));
return format;
}
}
public documentFormat getFormatByMimeType(String mimeType) {
Iterator it = this.documentFormats.iterator();
documentFormat format;
do {
if (!it.hasNext()) {
return null;
}
format = (documentFormat)it.next();
} while(!format.getMimeType().equals(mimeType));
return format;
}
}
运行
此代码在linux和window都可以运行
1.linux,将该项目,clear -> package后,将jar上传到linux,然后再使用java -jar xxx.jar,然后在浏览器访问项目的转换路径,就可以实现转换了
2.window,可以在浏览器访问该转换路径。但建议使用postman进行接口测试访问
postman进行接口测试访问
巩固Linux常用命令
cd / - - - 返回根目录
cd .. - - - 返回上一级
cd 某文件夹 - - - 进入某文件夹
rm -rf - - - 删除某文件夹或文件
rz - - - 从window系统上传文件到linux
sz - - - 从linux系统上传文件到window
3、openoffice乱码问题解决方法
步骤1 cd /usr/share/fonts 在这个目录下新建一个chinese文件夹 mkdir chinese
步骤2 把自己电脑的字体打包上传到这个文件夹
步骤3 执行下面几条命令 mkfontscale mkfontdir fc-cache -fv
步骤4 ps -ef|grep openoffice 查看当前office进程,杀死进程,kill -9 进程id
步骤5 重新启动 office nohup /opt/openoffice4/program/soffice -headless - accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard &



