前端Jquery,后端Java实现预览Word、Excel、PPT,pdf等文档
本人由于服务器配置或者项目版本旧的问题,试用了很多预览Word、Excel的方案,都没有实现,最后通过集成 LibreOffice+Jodconverter,先转成PDF,实现了文档的预览
1. LibreOffice 安装和配置
下载和安装:
访问https://www.libreoffice.org/download/download-libreoffice/
下载 Windows 64位版本
默认安装到 C:\Program Files\LibreOffice
2.java端引用包
<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工具服务类
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
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.后端试用
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 {// 转换文件为PDFboolean success = converterService.convertToPdf(inputPath, outputPath);if (success) {// 返回PDF预览URLrenderJson(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框架实现的
