本人由于服务器配置或者项目版本旧的问题,试用了很多预览Word、Excel的方案,都没有实现,最后通过集成 LibreOffice+Jodconverter,先转成PDF,实现了文档的预览
1. LibreOffice 安装和配置
下载和安装:
访问https://www.libreoffice.org/download/download-libreoffice/
下载 Windows 64位版本
默认安装到 C:\Program Files\LibreOffice
2.java端引用包
XML
<dependencies>
<!-- JODConverter 核心 -->
<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-local</artifactId>
<version>4.4.6</version>
</dependency>
<!-- 如果需要 Spring 集成 -->
<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-spring-boot-starter</artifactId>
<version>4.4.6</version>
</dependency>
</dependencies>
3. JODConverter工具服务类
java
import org.jodconverter.LocalConverter;
import org.jodconverter.office.LocalOfficeManager;
import org.jodconverter.office.OfficeException;
import org.jodconverter.office.OfficeManager;
import java.io.File;
public class JODConverterService {
private OfficeManager officeManager;
/**
* 启动 LibreOffice 服务
*/
public void startOfficeManager() {
try {
officeManager = LocalOfficeManager.builder()
.officeHome("C:/Program Files/LibreOffice")
.portNumbers(2002) // 设置端口
.build();
officeManager.start();
System.out.println("LibreOffice 服务启动成功");
} catch (OfficeException e) {
System.err.println("LibreOffice 服务启动失败: " + e.getMessage());
}
}
/**
* 停止 LibreOffice 服务
*/
public void stopOfficeManager() {
if (officeManager != null && officeManager.isRunning()) {
try {
officeManager.stop();
System.out.println("LibreOffice 服务已停止");
} catch (OfficeException e) {
System.err.println("停止 LibreOffice 服务失败: " + e.getMessage());
}
}
}
/**
* 转换文件为 PDF
*/
public boolean convertToPdf(String inputPath, String outputPath) {
if (officeManager == null || !officeManager.isRunning()) {
System.err.println("LibreOffice 服务未启动");
return false;
}
try {
File inputFile = new File(inputPath);
File outputFile = new File(outputPath);
// 确保输出目录存在
outputFile.getParentFile().mkdirs();
LocalConverter.builder()
.officeManager(officeManager)
.build()
.convert(inputFile)
.to(outputFile)
.execute();
System.out.println("文件转换成功: " + inputPath + " -> " + outputPath);
return true;
} catch (OfficeException e) {
System.err.println("文件转换失败: " + e.getMessage());
return false;
}
}
/**
* 检查 LibreOffice 是否可用
*/
public boolean isLibreOfficeAvailable() {
File officeHome = new File("C:/Program Files/LibreOffice");
File soffice = new File(officeHome, "program/soffice.exe");
return soffice.exists();
}
}
4.前端使用的是pdfJS查看pdf
javascript
function previewOfficeFile(id) {
$.ajax({
url: 'http://localhost:8081/tz02/platform/Preview/previewPath?id='+id,
type: 'GET',
success: function (data, status, xhr) {
if (data.status.state == "ok") {
let previewUrl = data.previewUrl;
var url = "/tz02/platform/Preview/pdfView?previewUrl=" + previewUrl;
window.open("#(__PUBLIC__)/pdfJs/web/viewer.html?file=" + encodeURIComponent(url));
} else {
layer.msg(data.message, {icon: 2, time: 2000});
}
},
error: function(xhr, status, error) {
// 处理错误
console.error('Error fetching docx file:', error);
}
});
}
5.后端试用
java
package com.tz.action.platform;
import com.jfinal.aop.Before;
import com.jfinal.core.Controller;
import com.jfinal.kit.LogKit;
import com.jfinal.kit.Ret;
import com.tz.interceptor.CheckLoginInterceptor;
import com.tz.model.ScmOperateManual;
import com.tz.util.JODConverterService;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@Before(CheckLoginInterceptor.class)
public class PreviewController extends Controller {
private static JODConverterService converterService = new JODConverterService();
// 静态初始化,启动 LibreOffice 服务
static {
if (converterService.isLibreOfficeAvailable()) {
converterService.startOfficeManager();
// 添加 JVM 关闭钩子,确保服务停止
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
converterService.stopOfficeManager();
}));
} else {
LogKit.info("未找到 LibreOffice,请先安装");
}
}
public void previewPath() {
Long id = getParaToLong("id");
LogKit.info("id====" + id);
ScmOperateManual operateManual = ScmOperateManual.dao.findById(id);
String fileName = operateManual.getFileNames();
String fileNameSub = fileName.substring(0, fileName.lastIndexOf(".") + 1);
String basePath = "E:/SCM/SCMDoc/";
String inputPath = basePath + fileName;
String outputPath = basePath + "temp/" + fileNameSub + ".pdf";
// 确保temp目录存在
File tempDir = new File(basePath + "temp");
if (!tempDir.exists()) {
tempDir.mkdirs();
}
try {
// 转换文件为PDF
boolean success = converterService.convertToPdf(inputPath, outputPath);
if (success) {
// 返回PDF预览URL
renderJson(Ret.ok("previewUrl", outputPath));
} else {
LogKit.info("转换失败");
renderJson(Ret.fail("message", "转换失败"));
}
} catch (Exception e) {
e.printStackTrace();
renderJson(Ret.fail("msg", "预览失败: " + e.getMessage()));
}
}
/**
* 文件预览接口
*/
public void previewPath2() {
String fileName = getPara("file");
String basePath = "E:/SCM/SCMDoc/";
String inputPath = basePath + fileName;
String outputPath = basePath + "temp/" + fileName + ".pdf";
// 确保 temp 目录存在
File tempDir = new File(basePath + "temp");
if (!tempDir.exists()) {
tempDir.mkdirs();
}
try {
// 检查输入文件是否存在
File inputFile = new File(inputPath);
if (!inputFile.exists()) {
LogKit.info("文件不存在 inputPath="+inputPath);
renderJson(Ret.fail("msg", "文件不存在: " + fileName));
return;
}
// 如果 PDF 已存在且比源文件新,直接使用
File pdfFile = new File(outputPath);
if (pdfFile.exists() && pdfFile.lastModified() > inputFile.lastModified()) {
renderJson(Ret.ok("previewUrl", outputPath));
return;
}
// 使用 LibreOffice 转换
boolean success = converterService.convertToPdf(inputPath, outputPath);
if (success) {
renderJson(Ret.ok("previewUrl", outputPath));
} else {
LogKit.info("转换失败");
renderJson(Ret.fail("message", "转换失败"));
}
} catch (Exception e) {
e.printStackTrace();
LogKit.error("预览异常: ", e);
}
}
/**
* pdf查看,根据路径查看
*/
@Before({CheckLoginInterceptor.class})
public void pdfView() {
getResponse().reset();
getResponse().setContentType("application/octet-stream");
getResponse().setCharacterEncoding("utf-8");
byte[] buff = new byte[1024];
BufferedInputStream bis = null;
OutputStream os = null;
// 查找均质材料报告信息
String urlPath = getPara("previewUrl");
getResponse().setHeader("Content-Disposition", "inline;filename=" + urlPath);
InputStream istream = null;
try {
LogKit.info("pdfView查看请求PDF路径:" + urlPath);
os = getResponse().getOutputStream();
istream = new FileInputStream(urlPath);
LogKit.info("pdfView 查看获取流结束。。。。");
bis = new BufferedInputStream(istream);
int i = 0;
while ((i = bis.read(buff)) != -1) {
os.write(buff, 0, i);
os.flush();
}
} catch (Exception e) {
e.printStackTrace();
LogKit.error("pdfView 查看pdf处理Exception:" + e.getMessage());
renderText("pdfView 查看失败");
} finally {
try {
if (os != null) {
os.close();
}
if (istream != null) {
istream.close();
}
if (bis != null) {
bis.close();
}
} catch (IOException e) {
LogKit.error("pdfView 查看pdf关闭流,Exception:" + e.getMessage());
}
}
renderNull();
}
}
后端代码是Jfinal框架实现的