Springboot实现doc,docx,xls,xlsx,ppt,pptx,pdf,txt,zip,rar,图片,视频,音频在线预览功能,你学“废”了吗?

news2024/11/23 10:37:24

最近工作中,客户需要生成包含动态内容的word/pdf报告,并且需要在线预览。

刚开始使用后台直接生成word文档,返回文件流给前端,浏览器预览会发生格式错乱问题,特别是文档中的图片有些还不显示。

想到最简单的办法就是后台将docx转换成pdf,前端预览一般就不会出问题。技术栈使用的是java,springboot那一套,所以调研了网上java文件预览相关的技术方案。比较主流的方案有以下几种:

1、Apache POI + Freemarker 或 Thymeleaf

这个算是最底层,最原始的实现方式,可以自定义模板和布局。

示例代码:

    // 加载模板
    Configuration cfg = new Configuration(Configuration.VERSION_2_3_29);
    cfg.setClassForTemplateLoading(MyClass.class, "/templates");
    Template template = cfg.getTemplate("template.ftl");
    // 数据模型
    Map<String, Object> dataModel = new HashMap<>();
    dataModel.put("title", "Report Title");
    dataModel.put("content", "Report content...");
    // 渲染模板到字符串
    StringWriter writer = new StringWriter();
    template.process(dataModel, writer);
    // 创建Word文档
    XWPFDocument document = new XWPFDocument();
    // 添加内容
    XWPFParagraph paragraph = document.createParagraph();
    XWPFRun run = paragraph.createRun();
    run.setText(writer.toString());
    // 保存
    FileOutputStream out = new FileOutputStream("report.docx");
    document.write(out);
    out.close();

缺点:使用起来很麻烦,需要熟悉大量API,自己搞定布局和样式,工作量太大

2、Aspose.Words for Java

这个应该是业界功能最强大的类库,有丰富的api和文档,可以轻松地将Word文档转换为PDF或HTML等格式。

示例代码,将docx文档转为pdf:

    private static File docx2Pdf(Long evaluateLogId, File wordFile) throws Exception {
        File tempPdf = createTempFile(evaluateLogId + "_final", ".pdf");
        try (ByteArrayInputStream docxIn = new ByteArrayInputStream(FileUtil.readBytes(wordFile))) {
            String name = "report_" + evaluateLogId + ".pdf";
            log.info("开始(docx to pdf)转换: {}", name);
            // 设置许可证
            License license = new License();
            license.setLicense("Aspose.Words.License");
            Document doc = new Document(docxIn);
            BuiltInDocumentProperties properties = doc.getBuiltInDocumentProperties();
            // 设置作者
            properties.setAuthor("xxx");
            doc.getWatermark().remove();
            doc.acceptAllRevisions();
            try (FileOutputStream os = new FileOutputStream(tempPdf)) {
                doc.save(os, SaveFormat.PDF);
            }
            log.info("转换完成: {}", name);
        }
        return tempPdf;
    }

上面代码是我使用的网上找的破解版本,需要设置许可证,可以正常转换,没有水印啥的。

需要破解包,可以扫码关注我回复 240813 aspose-words

但是,由于系统字体问题,再某些环境下可能有中文乱码问题,我在某一台开发服务器,ububtu系统,按照网上说法。加入中文字体,各种设置最后还是没有解决,时间紧任务重,后面也没有再试了,应该是字体相关配置问题。

缺点:功能要收费

3、Jodconverter  + LibreOffice/OpenOffice

jodconverter 是一个 Java 库,用于转换 OpenDocument 和 Microsoft Office 文档格式。它通过与 LibreOffice 或 Apache OpenOffice 连接来完成这些任务。jodconverter 可以在 Java 应用程序中实现自动化文档转换的功能,而无需用户交互。

jodconverter提供了两种模式调用底层Office库:

本地模式(Local Mode)

即在本地直接启动一个 LibreOffice 或 Apache OpenOffice 的实例来进行文档转换,每次转换都需要启动一个新的 LibreOffice 实例,比较耗资源,适合低到中等并发的应用场景。

如果要实现这种模式,需要修改dockerfile,将LibreOffice/OpenOffice集成到自己的应用中,随着容器启动,需要将Office的服务也以无头模式启动起来。

示例如下:

# 使用官方的 Java 运行时作为基础镜像
FROM openjdk:11-jdk-slim

# 设置工作目录
WORKDIR /app

# 将应用的 jar 包复制到容器中
COPY target/my-app.jar my-app.jar

# 下载 LibreOffice
RUN apt-get update && \
    apt-get install -y wget && \
    wget https://download.documentfoundation.org/libreoffice/stable/7.4/deb/x86_64/LibreOffice_7.4.2_Linux_x86-64_deb.tar.gz && \
    tar xzf LibreOffice_7.4.2_Linux_x86-64_deb.tar.gz && \
cd libreoffice* && \
    dpkg -i *.deb && \
    rm -rf /app/libreoffice* && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

# 设置 LibreOffice 无头模式启动命令
RUN echo 'export DISPLAY=:99' >> /etc/environment && \
echo 'export XAUTHORITY=/root/.Xauthority' >> /etc/environment && \
echo 'export HOME=/root' >> /etc/environment && \
    mkdir -p /root/.local/share/applications && \
echo "[Desktop Entry]" > /root/.local/share/applications/libreoffice-soffice.desktop && \
echo "Name=LibreOffice (soffice)" >> /root/.local/share/applications/libreoffice-soffice.desktop && \
echo "Exec=/usr/bin/soffice --headless --invisible --nologo --nodefaultfirst --norestore --nocrashreport --nofirststartwizard --accept='socket,host=localhost,port=2002;urp;StarOffice.ServiceManager'" >> /root/.local/share/applications/libreoffice-soffice.desktop && \
echo "Type=Application" >> /root/.local/share/applications/libreoffice-soffice.desktop && \
echo "MimeType=application/msword;application/vnd.openxmlformats-officedocument.wordprocessingml.document;" >> /root/.local/share/applications/libreoffice-soffice.desktop

# 启动 LibreOffice 服务
CMD ["/usr/bin/soffice", "--headless", "--invisible", "--nologo", "--nodefaultfirst", "--norestore", "--nocrashreport", "--nofirststartwizard", "--accept='socket,host=localhost,port=2002;urp;StarOffice.ServiceManager'"] && java -jar my-app.jar

使用代码示例:

public static void main(String[] args) {
8        // 创建 OfficeManager 实例
9        OfficeManager officeManager = new DefaultOfficeManagerBuilder()
10                .officeHome("/path/to/libreoffice") // 指定 LibreOffice 安装路径
11                .build();
12
13        // 启动 OfficeManager
14        officeManager.start();
15
16        try {
17            // 创建 PdfConverter
18            PdfConverter pdfConverter = new PdfConverter(officeManager);
19
20            // 指定源文件和目标文件
21            File source = new File("path/to/source.docx");
22            File target = new File("path/to/target.pdf");
23
24            // 转换文档
25            pdfConverter.convert(source, target);
26
27            System.out.println("Conversion completed.");
28        } catch (Exception e) {
29            e.printStackTrace();
30        } finally {
31            // 停止 OfficeManager
32            officeManager.stop();
33        }
34    }

缺点:jodconverter只是一个基础的中间库,底层依赖于LibreOffice/OpenOffice完成文档转换,配置麻烦

4、kkfileview

上面的方案都太麻烦,在网上找了好久,终于,kkFileView为文件文档在线预览解决方案,该项目使用流行的spring boot搭建,易上手和部署,基本支持主流办公文档的在线预览,如doc,docx,xls,xlsx,ppt,pptx,pdf,txt,zip,rar,图片,视频,音频等等。

底层原理 还是基于LibreOffice或OpenOffice,只不过kkfileview帮我们封装好了调用逻辑。

详细介绍,及使用文档,请参考官网地址:https://kkfileview.keking.cn/zh-cn/index.html


# 网络环境方便访问docker中央仓库
docker pull keking/kkfileview:4.1.0

# 网络环境不方便访问docker中央仓库
wget https://kkfileview.keking.cn/kkFileView-4.1.0-docker.tar
docker load -i kkFileView-4.1.0-docker.tar
docker run -it -p 8012:8012 keking/kkfileview:4.1.0

项目接入使用

后端返回文件流:


    @GetMapping("export-word")
    @Parameter(name = "id", description = "编号", required = true, example = "1")
    public void exportToWord(@RequestParam("id") Long id, HttpServletResponse response) throws Exception {
        wordReportService.exportToWord(id, response);
    }
    @Override
    public void exportToWord(Long id, HttpServletResponse response) {
        try {
            File doc = generateTmpDoc(id);
            response.setCharacterEncoding(StandardCharsets.UTF_8.name());
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Pragma", "No-cache");
            ServletUtils.writeAttachment(response, "report.docx", FileUtil.readBytes(doc));
            FileUtils.deleteQuietly(doc);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw ServiceExceptionUtil.exception(GlobalErrorCodeConstants.UNKNOWN);
        }
    }

写一段js脚本测试一下: 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>在线预览文件</title>
    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/js-base64@3.6.0/base64.min.js"></script>
    <script>document.addEventListener("DOMContentLoaded", function () {
        var rand = Math.floor(Math.random() * 1000000)
        var originUrl = 'http://192.168.8.5:80/admin-api/evaluate/log/report-preview?id=80&rand=' + rand; 
        // 要预览文件的访问地址
        var previewUrl = originUrl + '&fullfilename=report_' + rand + '.docx';
        window.open('http://192.168.8.7:8012/onlinePreview?url='+encodeURIComponent(Base64.encode(previewUrl)));        });</script>
</head>
<body><h1>test</h1></body>
</html>

预览成功,搞定。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2036549.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在原生未启用kdump的BCLinux 8系列服务器上启用kdump及报错处理

本文记录了在原生未启用kdump的BCLinux 8系列操作系统的服务器上手动启用kdump服务及报错处理的过程。 一、问题描述 BCLinux 8系列操作系统&#xff0c;系统初始化安装时未启用kdump服务&#xff0c;手动启动时报以下“No memory reserved for crash kernel”或“ConditionK…

数学建模——评价决策类算法(层次分析法、Topsis)

一、层次分析法 概念原理 通过相互比较确定各准则对于目标的权重, 及各方案对于每一准则的权重&#xff0c;这些权重在人的思维过程中通常是定性的, 而在层次分析法中则要给出得到权重的定量方法. 将方案层对准则层的权重及准则层对目标层的权重进行综合, 最终确定方案层对目标…

解读RPA自动化流程机器人

RPA全称Robotic Process Automation&#xff0c;即机器人流程自动化&#xff0c;基于人工智能和自动化技术&#xff0c;能够将大量重复、规则明确的日常事务操作实现自动化处理&#xff0c;通常被形象地称为“数字员工”。本文金智维将深入探讨RPA的主要价值和应用领域&#xf…

除悟空CRM外,主流的6大CRM私有部署的厂商

支持私有化部署的CRM有&#xff1a;1.纷享销客&#xff1b; 2.悟空CRM&#xff1b; 3.销售易&#xff1b; 4.有赞CRM&#xff1b; 5.知客CRM&#xff1b; 6.八骏CRM&#xff1b; 7.白码CRM。 面对日益复杂的网络环境和严峻的数据保护法规&#xff0c;私有化部署的CRM系统成为了…

论文阅读笔记:Semi-DETR: Semi-Supervised Object Detection with Detection Transformers

论文阅读笔记&#xff1a;Semi-DETR: Semi-Supervised Object Detection with Detection Transformers 1 背景1.1 动机1.2 问题 2 创新点3 方法4 模块4.1 分阶段混合匹配4.2 跨视图查询一致性4.3 基于代价的伪标签挖掘4.4 总损失 效果5.1 和SOTA方法对比5.2 消融实验 论文&…

Flink开发过程中遇到的问题

1. 任务启动报错Trying to access closed classloader. Exception in thread "Thread-5" java.lang.IllegalStateException: Trying to access closed classloader. Please check if you store classloaders directly or indirectly in static fields. If the st…

基于PSO-BP+BP多特征分类预测对比(多输入单输出) Matlab代码

基于PSO-BPBP多特征分类预测对比(多输入单输出) Matlab代码 1、和市面上的不同&#xff0c;运行一个main一键出对比图&#xff0c;非常方便 2、可以根据需要定制其他算法优化模型对比 程序已经调试好&#xff0c;无需更改代码替换数据集即可运行&#xff01;&#xff01;&…

Python | Leetcode Python题解之第334题递增的三元子序列

题目&#xff1a; 题解&#xff1a; class Solution:def increasingTriplet(self, nums: List[int]) -> bool:n len(nums)if n < 3:return Falsefirst, second nums[0], float(inf)for i in range(1, n):num nums[i]if num > second:return Trueif num > first…

C++字体库开发之EM长度单位转换九

freetype 设置EM // if (m_face) // FT_Set_Pixel_Sizes(*m_face, 0, pixelSize); // 动态宽&#xff0c;固定高 px // error FT_Set_Char_Size(face, /* face 对象的句柄 */ // 0, /* 以 …

Unity Audio

这章练习将介绍在unity中创建 audio&#xff08;音频&#xff09;的工具&#xff0c;培养的技能将帮助创建引人入胜的音频音景。完成本次学习后&#xff0c;能够使用 Unity 中的所有主要音频组件&#xff0c;为各种不同体验创建音频效果。 音频处理工具&#xff1a; Audacity…

Mintegral出海系列:解锁全球应用商店新增长路径

在全球化竞争的浪潮中&#xff0c;面对打法各异的应用和游戏品类&#xff0c;以及全球数百个环境不同的国家和地区&#xff0c;开发者们正面临着前所未有的挑战。Mintegral「出海ing」系列专题内容&#xff0c;助力出海开发者选准赛道探索新的增长路径。 据近期数据显示&#x…

LLM微调(精讲)-以高考选择题生成模型为例(DataWhale AI夏令营)

前言 你好&#xff0c;我是GISer Liu&#x1f601;&#xff0c;一名热爱AI技术的GIS开发者&#xff0c;上一篇文章中&#xff0c;作者介绍了基于讯飞开放平台进行大模型微调的完整流程&#xff1b;而在本文中&#xff0c;作者将对大模型微调的数据准备部分进行深入&#xff1b;…

凤凰端子音频矩阵应用领域

凤凰端子音频矩阵&#xff0c;作为一种集成了凤凰端子接口的音频矩阵设备&#xff0c;具有广泛的应用领域。以下是其主要应用领域&#xff1a; 一、专业音响系统 会议系统&#xff1a;在会议室中&#xff0c;凤凰端子音频矩阵能够处理多个话筒和音频源的信号&#xff0c;实现…

Luminar Neo for Mac/Win:创新AI图像编辑软件的强大功能

Luminar Neo&#xff0c;这款由Skylum公司倾力打造的图像编辑软件&#xff0c;为Mac和Windows用户带来了前所未有的创作体验与编辑便利。作为一款融合了先进AI技术的图像处理工具&#xff0c;Luminar Neo以其独特的功能和高效的操作流程&#xff0c;成为了摄影师、设计师及摄影…

使用Sanic和SSE实现实时股票行情推送

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storm…

【Next】全局样式和局部样式

不同于 nuxt &#xff0c;next 的样式绝大部分都需要手动导入。 全局样式 使用 sass 先安装 npm i sass -D 。 我们可以定义一个 styles 文件&#xff0c;存放全局样式。 variables.scss $fs30: 30px;mixin border() {border: 1px solid red; }main.scss use ./variables …

业界首个OpenTelemetry结合eBPF的向导式可观测性平台APO正式开源

AutoPilot Observability (简称APO&#xff09;是什么&#xff1f; 开箱即用的可观测性平台&#xff1a;APO 致力于提供一键安装、开箱即用的可观测性平台。APO 的 OneAgent 支持一键免配置安装 Tracing 探针&#xff0c;支持采集应用的故障现场日志、基础设施指标、应用和下游…

主机防火墙IPV6 域名 测试环境搭建及测试方法

由于国内当前网站支持ipv6的很少,部分支持ipv6 的网站由于路由器的限制,也无法直接访通过ipv6进行访问,因此进行主机防火墙ipv6域名测试时,需要自己搭建环境进行测试,以下为搭建环境的步骤。 1 . 搭建DNS服务器 环境:安装有python,系统为Windows Server 2016 DNS服务…

【Vue3】vue模板中如何使用enum枚举类型

简言 有的时候&#xff0c;我们想在vue模板中直接使用枚举类型的值&#xff0c;来做一些判断。 ts枚举 枚举允许开发人员定义一组命名常量。使用枚举可以更容易地记录意图&#xff0c;或创建一组不同的情况。TypeScript 提供了基于数字和字符串的枚举。 枚举的定义这里不说了…

haproxy最强攻略

1、负载均衡 负载均衡&#xff08;Load Balance&#xff0c;简称 LB&#xff09;是高并发、高可用系统必不可少的关键组件&#xff0c;目标是 尽力将网络流量平均分发到多个服务器上&#xff0c;以提高系统整体的响应速度和可用性。 负载均衡的主要作用如下&#xff1a; 高并发…