前端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端引用包

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框架实现的

相关推荐
我有一棵树6 小时前
浏览器使用 <embed> 标签预览 PDF 的原理
pdf·embed
Sam_Deep_Thinking7 小时前
EasyExcel 流式处理中实现末尾行过滤的技术方案
excel
程序员小羊!11 小时前
Flink(用Scala版本写Word Count 出现假报错情况解决方案)假报错,一直显示红色报错
flink·word·scala
蜀中廖化12 小时前
小技巧:ipynb转pdf
pdf·小工具·python to pdf
Eiceblue14 小时前
使用 Python 向 PDF 添加附件与附件注释
linux·开发语言·vscode·python·pdf
Eiceblue14 小时前
React 前端实现 Word(Doc/Docx)转 HTML
前端·react.js·word
usdoc文档预览15 小时前
前端Word文件在线预览-文件预览修改背景色,动态修改在线预览颜色
前端·word
蛋王派15 小时前
本地部署DeepSeek-OCR:打造高效的PDF文字识别服务
人工智能·自然语言处理·pdf·ocr
Iloveskr15 小时前
markdown转为pdf导出
java·pdf