拓冰建站拓冰建站
首页 / 资讯中心 / 正文

kkfileview 开源文档在线预览:Docker 部署与生产实践

上周有个读者在群里问他们公司内部知识库想把上传的 Word、Excel、PPT 直接在线打开不想让用户下载后再看问我有没有轻量方案。我第一反应就是 kkfileview一个用 Java 写的开源文档在线预览服务。这类需求其实很普遍像 OA、合同管理、网盘、工单系统只要涉及附件上传几乎都会遇到“文件传上来了怎么让用户直接在浏览器里看”的问题。kkfileview 就是解决这个问题的。它支持 doc、docx、xls、xlsx、ppt、pptx、pdf、txt、图片、音频、视频、压缩包等格式部署也不复杂Docker 一条命令就能跑起来。我前后在生产环境里用过三套部署Docker 单机、源码定制、以及配合 Redis 的多实例踩过的坑不少。下面我按“选型—准备—安装—使用—排查—生产”这个顺序把整个流程拆开讲一遍适合刚接触这个项目的新手也适合准备上生产的运维和开发。1. 为什么选 kkfileview核心定位与方案对比1.1 文件预览的常见痛点与 kkfileview 的切入方式很多人第一次做附件预览最容易想到的是前端直接渲染。图片和 PDF 确实可以但遇到 Office 文件就头疼了浏览器原生打不开 docxxlsx 更是没法直接显示用前端 js 库比如 mammoth.js 能转 docx但复杂表格、页眉页脚、公式基本会丢SheetJS 能解析 xlsx可样式和打印效果很难保证。再往后考虑服务端转换用 LibreOffice 或 OpenOffice 把 Office 转成 PDF再让浏览器看 PDF这条路线稳定得多但需要自己封装转换队列、处理并发、管理临时文件工作量并不小。kkfileview 的核心价值就在于它把“服务端转换 前端预览”这一整套流程打包好了。你不需要自己调 LibreOffice 命令行也不用手写 PDF 分页预览。它对外只暴露一个 HTTP 接口传入文件的 URL返回一个可嵌入 iframe 的预览页面。对于业务系统来说集成成本极低前端只要拼一个链接iframe 一嵌用户就能看。这种“一个接口解决所有格式”的思路特别适合后台管理系统、知识库、工单附件、合同查阅这类场景。我自己最早是用 OpenOffice 转换脚本写了三百多行最怕遇到并发转换把进程卡死后来换成 kkfileview最直观的感受是省心。它内部对转换进程有超时控制支持缓存还能配置水印和禁止下载。当然它也不是万能的比如超大 Excel 的渲染、复杂排版的 Word效果取决于 LibreOffice 的转换质量但日常办公文件 95% 以上都能正常预览。1.2 与其他预览方案横向对比市面上做文件预览的方案很多我把常见的几类列出来方便你判断 kkfileview 到底适合什么位置。对比维度包括部署难度、支持格式、样式还原、二次开发成本、资源占用。方案类型代表工具/服务支持格式样式还原度部署难度资源占用适合场景前端纯 JS 解析mammoth.js、SheetJSdocx、xlsx 为主一般样式易丢很低低简单文本、表格预览服务端转换LibreOffice 自研接口Office、PDF、图片较高中等偏高中高有开发能力、需深度定制开源预览服务kkfileviewOffice、PDF、图片、音视频、压缩包较高低到中等中高后台系统、知识库、OA商业云预览各家云文档服务很全很高低按量付费不差钱、不想运维浏览器原生PDF.js、图片标签PDF、图片高低低仅 PDF/图片从表格能看出来kkfileview 的定位非常清晰它比纯前端方案支持格式多得多比自研转换方案省人力又比商业云服务可控、免费。如果你需要一个能自己部署、支持格式全、集成简单的预览服务kkfileview 基本是首选。有人会拿 open file view 和 kkfileview 做对比前者更偏向轻量查看后者在格式覆盖、缓存、水印、集群这些生产特性上更完整。实际选型时先看你的文件类型如果主要是 Office 和 PDFkkfileview 足够。还有一点值得说kkfileview 是 Java 技术栈和大多数国内后台系统Spring Boot、Spring Cloud天然亲近。你可以把它当成一个独立服务部署也可以把源码拉下来嵌入自己的项目。对于运维来说Docker 镜像已经内置了 LibreOffice 和常用字体少去了很多环境折腾。对于开发来说接口简单文档清楚遇到问题查 issue 也方便。1.3 部署形态选择Docker 还是源码决定用 kkfileview 之后第一个要做的选择就是部署形态。Docker 部署最省事官方镜像里已经装好了 LibreOffice、字体、JDK拉下来就能跑。适合快速验证、中小规模生产、不想折腾系统的团队。源码部署更适合需要改源码、定制水印逻辑、调整转换参数、集成自己认证体系的场景。比如我们有个项目要求预览链接必须带一次性 token且要记录谁在什么时候看了哪个文件这种就要改源码或者在外层加网关。Docker 的缺点也有镜像体积不小通常 1GB 以上如果要装特殊字体得自己打镜像或者挂载字体目录容器内 LibreOffice 转换有时会遇到权限问题。源码部署的缺点是环境依赖多JDK 版本、LibreOffice 版本、字体、中文字体缓存每一步都可能翻车。我的建议是先用 Docker 跑通确认功能满足如果后续需要深度定制再拉源码。不要一上来就源码部署容易在环境上耗掉一整天。另外如果你的文件量很大比如每天几万次预览单机 Docker 可能扛不住这时候要考虑多实例 Redis 缓存 Nginx 负载均衡。这个后面会详细讲。先明确一点kkfileview 本身是无状态服务转换结果可以缓存到 Redis 或本地多实例部署并不复杂。但前提是你把临时目录和缓存配置好否则会出现 A 实例转换、B 实例读取不到的问题。2. 环境准备安装前的依赖清单与参数规划2.1 操作系统与硬件建议kkfileview 官方推荐 Linux实际在 CentOS 7/8、Ubuntu 20.04/22.04、Debian 上都能跑。Windows 也能部署但生产环境不建议因为 LibreOffice 在 Windows 下的进程管理和字体路径更容易出问题。我自己的生产环境用的是 Ubuntu 22.04 LTS内核 5.15跑了两年比较稳。如果你用 CentOS注意 7 已经停止维护尽量换 Rocky Linux 或 AlmaLinux。硬件方面官方没有特别高的要求但文件预览是 CPU 和内存密集型操作尤其是 Office 转 PDF。我的经验值2 核 4G 可以支撑每天几百次预览4 核 8G 可以支撑每天几千次8 核 16G 以上适合上万次并配合缓存。内存主要吃在 LibreOffice 进程和 JVM 堆上如果同时转换多个大文件内存会飙升。磁盘方面临时文件目录要有足够空间一个 50MB 的 Word 转 PDF 可能产生几百 MB 临时文件建议至少预留 20GB并定期清理。还有一点容易忽略文件系统。如果挂载的是 NFS 或网络存储LibreOffice 读写临时文件可能很慢甚至锁不住。尽量用本地 SSD。如果必须用网络存储把临时目录指向本地盘转换完成后再把结果写回网络存储。这个坑我在一个客户现场遇到过预览一个 10MB 的 PPT 要 20 秒换成本地盘后降到 3 秒。2.2 必需依赖JDK、LibreOffice、字体、RedisDocker 部署时这些依赖都打包好了但源码部署必须自己装。JDK 要求 1.8 以上建议 JDK 11 或 17。LibreOffice 是核心版本建议 7.0 以上太低会有些新格式不支持。安装命令在 Ubuntu 下是apt install libreoffice libreoffice-l10n-zh-cnCentOS 下可以用 yum 或直接下载 tar 包。注意不要装 OpenOfficekkfileview 默认走 LibreOffice。字体是中文预览的命门。Linux 服务器默认只有少量西文字体中文 Word 转 PDF 后全是方块。必须安装中文字体比如文泉驿、思源黑体、宋体、微软雅黑。我通常把 Windows 的C:\Windows\Fonts里常用字体拷贝到/usr/share/fonts/chinese然后执行fc-cache -fv刷新缓存。注意版权问题生产环境用开源字体更稳妥比如fonts-wqy-zenhei、fonts-noto-cjk。装完用fc-list :langzh检查是否识别到中文。Redis 是可选的但强烈建议生产环境启用。kkfileview 默认用本地缓存多实例会不一致。配置 Redis 后转换结果和文件信息可以共享还能设置过期时间避免磁盘被撑满。Redis 安装本身不复杂但要注意和 kkfileview 的网络延迟尽量同机房。如果不用 Redis至少要把本地缓存目录挂载到持久化盘并设置定时清理。2.3 端口与目录规划、内存计算kkfileview 默认端口是 8012这个端口不冲突的话直接用。如果前面有 Nginx可以把 8012 只监听内网外网走 80/443 反向代理。目录规划建议分成三块配置目录、临时文件目录、日志目录。Docker 部署时通过-v挂载源码部署时在application.properties里指定。我通常这样规划配置目录/data/kkfileview/config临时文件目录/data/kkfileview/file日志目录/data/kkfileview/logs内存计算有个粗略公式JVM 堆 LibreOffice 单进程内存 × 并发数 系统缓存。LibreOffice 转换一个普通 Office 文件大约占用 200-500MB 内存大文件可能上 1GB。假设你允许同时转换 5 个文件JVM 堆设 2GB那么总内存至少 2GB 5×500MB 系统 2GB ≈ 6.5GB所以 8GB 内存比较稳妥。JVM 参数可以在启动脚本里设置-Xms1g -Xmx2g不要设太大否则系统缓存不够反而变慢。另外文件上传大小限制也要提前规划。kkfileview 默认可能限制 100MB可以在配置文件里改spring.servlet.multipart.max-file-size和max-request-size。如果你的业务有 500MB 的视频或压缩包记得同步调整 Nginx 的client_max_body_size。这些参数不提前规划上线后用户传个大文件就会报错。2.4 安装包获取与校验Docker 方式直接拉镜像命令是docker pull keking/kkfileview:4.4.0。建议固定版本号不要用 latest避免自动升级带来不兼容。拉取后可以用docker images看镜像大小通常 1.5GB 左右。如果公司网络不能直接拉 Docker Hub可以找国内镜像源或者把镜像导出成 tar 包再用docker load导入。源码方式从 GitHub 或 Gitee 拉取注意选择稳定分支比如v4.4.0。下载后一定要校验。Docker 镜像可以用docker inspect看构建时间源码可以核对 commit id 或 release 包哈希。我见过有人从第三方下载了被篡改的 jar结果启动后疯狂外连虽然是极端情况但生产环境必须走官方渠道。如果是离线环境提前把镜像、LibreOffice 安装包、字体包都准备好避免现场抓瞎。3. Docker 方式安装 kkfileview最快跑通的路径3.1 拉取镜像与启动命令逐行拆解Docker 部署是我最推荐的上手方式。下面这条命令可以直接复制但每一段都要理解docker run -d \ --name kkfileview \ --restartalways \ -p 8012:8012 \ -e TZAsia/Shanghai \ -v /data/kkfileview/config:/opt/kkfileview/config \ -v /data/kkfileview/file:/opt/kkfileview/file \ -v /data/kkfileview/logs:/opt/kkfileview/logs \ keking/kkfileview:4.4.0逐行解释-d后台运行--restartalways让容器随 Docker 启动服务器重启后自动恢复-p 8012:8012映射端口-e TZAsia/Shanghai设置时区这个非常重要否则日志时间和文件过期时间会差 8 小时-v挂载配置、临时文件、日志目录保证容器删了数据还在。镜像名keking/kkfileview:4.4.0是官方仓库版本号按需改。启动后执行docker logs -f kkfileview看到 “Started KKFileViewApplication” 就算成功。如果失败多半是端口占用或挂载目录权限不对。挂载目录要先mkdir -p并给写权限比如chmod 777 /data/kkfileview生产环境可以给特定用户但简单起见先放开。注意如果你不挂载 config容器内用的是默认配置改了也不持久所以一定要挂。还有一个细节官方镜像内 LibreOffice 的安装路径可能是/opt/libreoffice7.6配置文件里office.home要指向它。如果你自己打镜像换了路径记得同步改application.properties。Docker 部署省事就省在这里默认配置基本能跑不用自己装 LibreOffice。3.2 挂载配置文件与自定义预览参数第一次启动后容器内会生成默认的application.properties。你可以执行docker cp kkfileview:/opt/kkfileview/config/application.properties /data/kkfileview/config/把它拷出来然后修改。重点参数我列几个server.port8012服务端口。file.upload.max-size100MB上传大小限制。cache.enabledtrue开启缓存。cache.typeredis缓存类型默认是default本地缓存生产建议 redis。spring.redis.host127.0.0.1Redis 地址。watermark.enabledtrue开启水印。watermark.txt内部资料水印文字。office.preview.typepdfOffice 预览方式可选 pdf、image。office.home/opt/libreoffice7.6LibreOffice 路径。改完配置后重启容器docker restart kkfileview。如果配置有语法错误容器会启动失败看日志就能定位。我建议把配置文件纳入版本管理每次改动记录原因。比如水印文字根据租户不同可以做成环境变量注入但 kkfileview 原生不支持多租户水印需要改源码或外层代理。还有一个常用参数是file.dir指定临时文件目录。默认可能在/opt/kkfileview/file挂载后就是宿主机的/data/kkfileview/file。这个目录会随着预览次数增长必须定期清理。可以写个 crontab每天凌晨删除 7 天前的文件find /data/kkfileview/file -type f -mtime 7 -delete。注意不要删正在使用的文件最好在业务低峰期执行。3.3 验证部署健康检查与预览测试容器起来后先访问http://服务器IP:8012如果能看到 kkfileview 的首页说明服务正常。接着用一个真实的文件测试。最简单的办法是准备一个公网可访问的 PDF 或 Word 链接然后拼预览地址http://服务器IP:8012/onlinePreview?urlBase64编码后的文件URL注意Base64 编码后还要做 URL 编码否则、/、会出问题。你可以用在线工具先测比如文件 URL 是http://example.com/test.docxBase64 后是aHR0cDovL2V4YW1wbGUuY29tL3Rlc3QuZG9jeA再 URL 编码得到aHR0cDovL2V4YW1wbGUuY29tL3Rlc3QuZG9jeA%3D%3D。拼起来访问如果能正常预览说明部署成功。如果预览报错先看容器日志。常见错误有连接文件 URL 超时、LibreOffice 转换失败、字体缺失。如果是文件 URL 是内网地址kkfileview 容器需要能访问到否则会 404。测试时尽量用公网文件或者把文件放到容器能访问的内网 HTTP 服务上。另外浏览器控制台如果有跨域错误是因为你用了 iframe 嵌入kkfileview 默认允许跨域一般不用改。3.4 Docker 部署的常见坑与修复第一个坑时区不对。表现是预览链接过期时间、日志时间差 8 小时。解决就是加-e TZAsia/Shanghai并且挂载/etc/localtime:/etc/localtime:ro也可以。第二个坑字体缺失。中文 Word 预览全是方块。解决是挂载字体目录比如-v /usr/share/fonts:/usr/share/fonts:ro但更推荐自己构建镜像时把字体 COPY 进去。第三个坑权限问题。挂载目录如果属主是 root容器内用户可能写不进去日志报 Permission denied。解决是chmod -R 777或指定用户。第四个坑LibreOffice 进程残留。长时间运行后容器内可能有一堆soffice.bin僵尸进程导致内存耗尽。解决是设置转换超时kkfileview 有office.convert.timeout参数默认可能 300 秒可以调小到 120 秒。同时定期重启容器比如每天凌晨重启一次。第五个坑镜像体积大拉取慢。可以配置 Docker 镜像加速或者用离线 tar 包。这些坑我都踩过最影响生产的是字体和进程残留前者导致用户看到乱码后者导致服务假死。4. 源码方式安装 kkfileview可控性更强的部署4.1 拉取源码与目录结构速览源码部署适合需要定制的情况。先拉代码git clone https://github.com/kekingcn/kk-file-view.git cd kk-file-view git checkout v4.4.0目录结构大致是src/main/java放 Java 代码src/main/resources放配置和模板web放前端静态资源。核心包有controller、service、utils、config。OnlinePreviewController是对外接口OfficeConvertService负责调 LibreOfficeCacheService管缓存。如果你想改水印找WatermarkUtils想改文件类型白名单找FileTypeUtils。先花半小时看一遍目录后面改起来不迷路。源码依赖 Maven确保本地有 Maven 3.6 和 JDK 11。编译前先检查pom.xml里的版本有些依赖可能从中央仓库拉不到需要配国内镜像。编译命令mvn clean package -DskipTests成功后会在target目录生成kk-file-view.jar。如果编译报错多半是 JDK 版本不对或依赖下载失败。可以加上-U强制更新依赖。打包后先本地运行测试java -jar target/kk-file-view.jar --spring.config.locationfile:/data/kkfileview/config/application.properties看到启动日志后用同样的 onlinePreview 接口测试。4.2 修改配置文件 application.properties 关键项源码部署的配置文件和 Docker 版基本一致但路径要根据实际环境改。比如office.home要指向你安装的 LibreOffice 目录常用的是/opt/libreoffice7.6或/usr/lib/libreoffice。file.dir要指向有写权限的目录比如/data/kkfileview/file。如果要用 Redis配置spring.redis.host、port、password。如果要用本地缓存设置cache.typedefault并确保cache.dir可写。还有一个重要配置是server.tomcat.max-threads默认可能 200如果并发预览多可以调大到 500。但要注意内存线程越多同时转换的文件越多。可以配合office.convert.max-threads限制同时转换数比如设为 4避免 LibreOffice 把 CPU 跑满。这个参数很关键我见过有人不限制结果 10 个用户同时预览大 Excel服务器直接卡死。日志配置也建议改。默认日志可能只输出到控制台生产环境要输出到文件并切割。可以在application.properties里设置logging.file.name/data/kkfileview/logs/kkfileview.log并用 logback 配置按天切割。这样出问题可以回溯。另外把logging.level.cn.kekingdebug打开能看到更多转换细节但会增大日志量排障后再关掉。4.3 编译打包与启动脚本编译完成后不要直接java -jar裸跑最好写个启动脚本设置 JVM 参数和时区。示例#!/bin/bash export JAVA_HOME/usr/lib/jvm/java-11-openjdk export PATH$JAVA_HOME/bin:$PATH nohup java -Xms1g -Xmx2g \ -Dfile.encodingUTF-8 \ -Duser.timezoneAsia/Shanghai \ -jar /data/kkfileview/kk-file-view.jar \ --spring.config.locationfile:/data/kkfileview/config/application.properties \ /data/kkfileview/logs/start.log 21 -Dfile.encodingUTF-8防止中文乱码-Duser.timezone设置时区。-Xms和-Xmx设成一样可以避免堆动态调整带来的抖动。启动后tail -f看日志如果报Address already in use说明端口冲突改server.port或杀进程。如果报No such file检查配置路径。做成 systemd 服务更规范可以开机自启、崩溃重启。写一个/etc/systemd/system/kkfileview.serviceExecStart指向启动脚本Restartalways。这样比 nohup 靠谱。如果你公司有容器平台还是建议用 Docker源码方式维护成本更高升级要重新编译打包。4.4 与 Nginx 配合反向代理与 URL 编码处理生产环境一般不会直接暴露 8012而是通过 Nginx 反向代理加 HTTPS、限流、认证。配置示例server { listen 80; server_name preview.example.com; location / { proxy_pass http://127.0.0.1:8012; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; client_max_body_size 200m; proxy_read_timeout 300s; } }注意proxy_read_timeout要调大因为 Office 转换可能超过 60 秒。如果预览大文件频繁超时Nginx 会报 504。client_max_body_size根据最大文件调整。如果开了 HTTPSiframe 嵌入的页面也要用 HTTPS否则浏览器会拦截混合内容。URL 编码是 Nginx 代理里最容易出问题的地方。onlinePreview?urlxxx里的xxx是 Base64 再 URL 编码Nginx 默认会解码一次如果后端再解一次可能出错。实测下来只要代理层不做额外的rewrite解码直接透传即可。如果遇到变成空格检查前端编码是否正确。我通常在前端生成链接时就用encodeURIComponent包一层后端接收后用URLDecoder解一次再 Base64 解。这个顺序不能乱。5. 核心使用如何在自己的系统里调用预览接口5.1 onlinePreview 接口的 URL 编码规则与生成逻辑kkfileview 的核心接口只有一个/onlinePreview。参数url必须是“文件原始 URL 的 Base64 编码”并且整个 Base64 字符串要做 URL 编码。为什么这么设计因为文件 URL 可能带查询参数、中文、特殊字符直接拼进链接会乱Base64 能保证安全但 Base64 本身包含、/、这些在 URL 里有特殊含义所以还要再 URL 编码。顺序是原始文件 URL - UTF-8 字节 - Base64 - URL 编码 - 拼到onlinePreview?url后面。举个例子文件 URL 是https://oss.example.com/合同 2024.docx。先 UTF-8 编码Base64 得到一串字符再用encodeURIComponent处理得到最终参数。后端收到后先 URL 解码再 Base64 解码还原出文件 URL。如果中间少了一步就会预览失败。很多新手直接Base64.encode(fileUrl)拼上去结果文件 URL 里没有特殊字符时能看一遇到带的 URL 就失败。这个坑非常典型。另外kkfileview 还支持传其他参数比如fullfilename指定文件名watermarkTxt指定水印文字officePreviewType指定预览方式。这些参数也要 URL 编码。比如你想强制用图片方式预览 Office可以加officePreviewTypeimage。但注意参数多了链接会很长浏览器和 Nginx 都有 URL 长度限制一般 8KB 以内没问题。5.2 前端集成示例Java、Python、JavaScript 生成预览链接实际集成时你需要在后端生成预览链接返回给前端。下面是三种语言的示例。Javaimport java.net.URLEncoder; import java.util.Base64; import java.nio.charset.StandardCharsets; public class PreviewUtil { public static String buildPreviewUrl(String fileUrl) throws Exception { String base64 Base64.getEncoder() .encodeToString(fileUrl.getBytes(StandardCharsets.UTF_8)); String encoded URLEncoder.encode(base64, UTF-8); return http://preview.example.com/onlinePreview?url encoded; } }Pythonimport base64 import urllib.parse def build_preview_url(file_url): b64 base64.b64encode(file_url.encode(utf-8)).decode(utf-8) encoded urllib.parse.quote(b64, safe) return fhttp://preview.example.com/onlinePreview?url{encoded}JavaScriptfunction buildPreviewUrl(fileUrl) { const b64 btoa(unescape(encodeURIComponent(fileUrl))); const encoded encodeURIComponent(b64); return http://preview.example.com/onlinePreview?url${encoded}; }注意 Java 的URLEncoder.encode会把空格编成而 URL 标准里空格应该是%20。有些场景下会被后端当成空格导致 Base64 解码失败。保险做法是编码后再把替换成%20。Python 的quote默认不编码/但 Base64 里可能有/所以要用safe强制编码。JavaScript 的btoa不能直接处理中文要先encodeURIComponent再unescape转成 Latin-1。这些细节不处理好预览就会时好时坏。5.3 文件流、远程 URL、本地路径三种调用方式kkfileview 支持三种文件来源。第一种是远程 URL最常见文件放在 OSS、MinIO、Nginx 静态目录只要 kkfileview 能访问到就行。第二种是文件流适合文件不公开、需要鉴权的场景但 kkfileview 原生接口主要接收 URL如果要传流需要改源码或者先把文件传到 kkfileview 能访问的临时地址。第三种是本地路径比如file:///data/files/test.docx但出于安全考虑官方默认可能禁用需要配置file.local.enabledtrue并限制目录。生产环境我推荐远程 URL 方式。业务系统上传文件到对象存储生成一个带时效的签名 URL再把这个 URL 传给 kkfileview。这样 kkfileview 不需要存储文件也不涉及权限文件访问控制由对象存储负责。注意签名 URL 的有效期要大于预览时间否则用户看到一半链接过期就会加载失败。一般设 30 分钟以上大文件设 1 小时。如果文件在私网kkfileview 和文件服务要在同一网络或者配置代理。不要直接把内网地址暴露给 kkfileview 的公网实例容易有 SSRF 风险。可以在 kkfileview 前面加一层网关校验文件 URL 的域名白名单。kkfileview 本身也支持security.whitelist配置限制允许访问的域名。这个安全点后面还会讲。5.4 预览效果调优缓存、水印、禁止下载、过期清理预览效果调优有几个常用开关。缓存能大幅提升二次打开速度尤其是同一个文件被多次预览时。配置cache.enabledtrue本地缓存用cache.typedefault集群用cache.typeredis。缓存时间cache.timeout可以设 3600 秒避免文件更新后一直看旧版。如果文件经常变缓存时间设短一点比如 300 秒。水印配置watermark.enabledtruewatermark.txt填文字。但默认水印是平铺的位置和透明度可以在源码里调。禁止下载可以通过office.preview.typeimage让 Office 转成图片用户无法直接下载原文件PDF 也可以转图片。但这样会损失文字可选性。如果既要禁止下载又要保留文字只能在前端加遮罩防君子不防小人。过期清理很重要。file.dir下的临时文件如果不清理磁盘很快满。除了定时任务kkfileview 也有file.clean.timeout之类的参数但不同版本可能不一样最好自己控制。我通常写一个脚本每天凌晨 2 点删除 3 天前的文件。同时监控磁盘使用率超过 80% 告警。Redis 缓存也要设过期时间避免内存无限增长。6. 常见问题与排查技巧实录6.1 预览乱码、字体缺失、中文不显示中文乱码是最高频的问题。表现是 Word 转 PDF 后中文变成方框或问号。根因是服务器缺少中文字体。排查步骤进入容器或服务器执行fc-list :langzh如果没有输出说明没装中文字体。解决安装fonts-wqy-zenhei或拷贝字体到/usr/share/fonts然后fc-cache -fv。Docker 部署时可以自己写 Dockerfile 把字体 COPY 进去或者用-v挂载字体目录。如果装了字体还是乱码检查 LibreOffice 是否识别。执行libreoffice --headless --convert-to pdf test.docx看生成的 PDF 是否正常。如果命令行正常但 kkfileview 乱码可能是 kkfileview 用的字体目录和系统不一致检查office.home下的字体配置。另外某些特殊字体如宋体、黑体有版权Linux 上可以用思源字体替代但替换后排版可能略有差异。还有一个隐蔽问题文件本身编码。有些 txt 文件是 GBK 编码kkfileview 默认按 UTF-8 读就会乱码。可以在预览参数里指定编码或者转成 UTF-8 再上传。这个场景在老旧系统迁移时很常见遇到 txt 乱码先确认文件编码。6.2 转换失败、进程卡死、内存溢出转换失败的表现是页面一直转圈最后报“转换失败”或超时。先看日志搜索convert或soffice。常见原因LibreOffice 进程卡死、文件损坏、磁盘满、内存不足。如果是进程卡死执行ps -ef | grep soffice看有没有残留进程有就 kill 掉然后重启 kkfileview。长期方案是设置转换超时office.convert.timeout120并限制并发数。内存溢出表现为容器被 OOM Killer 杀掉或者 Java 抛OutOfMemoryError。解决调大 JVM 堆-Xmx4g但不要超过物理内存的 70%限制同时转换数office.convert.max-threads4定期重启容器。如果单个文件特别大比如 200MB 的 ExcelLibreOffice 可能直接崩溃这种只能提前限制文件大小或者在业务层拒绝。我遇到过最诡异的一次是转换特定 PPT 时卡死日志没有任何错误。后来用命令行单独转也卡死确定是 LibreOffice 的 bug升级版本后解决。所以遇到无法解释的转换失败先确认 LibreOffice 版本尽量用官方推荐版本。6.3 远程文件 403/404、跨域与反向代理预览报 403说明 kkfileview 请求文件 URL 被拒绝。检查文件 URL 是否带签名、签名是否过期、kkfileview 服务器 IP 是否在白名单。报 404说明文件 URL 写错或文件不存在。如果是内网 URL确认 kkfileview 能否 ping 通、能否 curl 到。可以在容器内执行curl -I 文件URL测试。跨域问题通常不是 kkfileview 本身而是 iframe 嵌入的页面和父页面不同源。kkfileview 默认允许跨域如果还有问题检查 Nginx 是否加了X-Frame-Options或 CSP。反向代理常见问题是路径重写导致url参数被二次编码。解决Nginx 配置里不要对onlinePreview做 rewrite直接proxy_pass到后端。如果必须重写确保url参数原样透传。还有一个坑是 HTTPS 混合内容。父页面是 HTTPS预览 iframe 是 HTTP浏览器会拦截。解决给 kkfileview 也配 HTTPS或者用 Nginx 统一入口。证书可以用 Lets Encrypt配置不复杂。6.4 性能调优与安全加固SSRF、文件类型白名单性能调优的核心是缓存和并发控制。开启 Redis 缓存后同一文件二次预览直接从缓存读不用再调 LibreOffice。并发控制通过office.convert.max-threads限制避免 CPU 打满。如果预览量很大可以部署多个 kkfileview 实例前面挂 Nginx 负载均衡共享 Redis 缓存。文件临时目录可以各自本地但缓存要共享。安全加固不能忽视。kkfileview 接收一个 URL 并去请求天然有 SSRF 风险。攻击者可能传入http://169.254.169.254/latest/meta-data/探测云元数据或者扫描内网。必须配置域名白名单只允许业务需要的文件域名。kkfileview 有security.whitelist参数可以配置允许的域名。同时限制文件类型禁止预览可执行文件、脚本文件配置file.type.whitelist。还要限制文件大小防止大文件拖垮服务。另外预览接口不要直接暴露公网最好加认证。可以在 Nginx 层加 token 校验或者用网关鉴权。kkfileview 本身没有复杂的权限体系它更适合作为内网服务。如果必须公网访问一定要加 HTTPS、限流、白名单、日志审计。7. 生产环境经验高可用与监控7.1 多实例部署与 Redis 缓存单机 kkfileview 在预览量上来后容易成为瓶颈。多实例部署是标准方案部署 2 到 4 个容器前面用 Nginx 负载均衡Redis 作为共享缓存。注意几个点所有实例的application.properties要一致尤其是 Redis 地址和缓存前缀文件临时目录各自本地即可因为缓存命中时不需要文件Redis 要设置密码和持久化避免缓存丢失后大量回源转换。Nginx 负载均衡可以用upstream配置健康检查可以用max_fails和fail_timeout。如果某个实例挂了Nginx 自动剔除。kkfileview 没有内置健康检查接口可以配置一个简单的/路径检查返回 200 即可。多实例下水印和预览参数要保持一致否则用户刷新后可能看到不同效果。Redis 缓存 key 的命名要避免冲突。kkfileview 默认用文件 URL 的 MD5 或类似方式做 key一般不会冲突。但如果多个业务共用 Redis最好加前缀在配置里改cache.prefix。缓存过期时间根据文件更新频率设置合同类文件可以长一点日志类文件短一点。7.2 日志监控与文件清理日志是排障的生命线。生产环境要把日志输出到文件并配置切割。用 logback 按天切割保留 30 天。同时接入监控系统比如 Prometheus Grafana监控 JVM 内存、CPU、转换队列长度、失败率。kkfileview 暴露的指标有限可以在 Nginx 层统计请求量和响应时间。如果失败率突然上升第一时间看日志里的convert error。文件清理要自动化。file.dir下的临时文件会越积越多写一个定时脚本每天清理 3 天前的文件。同时监控磁盘超过 80% 告警。Redis 缓存也要监控内存避免打满。如果发现缓存命中率很低检查缓存配置是否生效或者文件 URL 是否每次都带不同签名导致 key 变化。签名 URL 做缓存 key 时最好去掉签名参数只保留文件路径否则缓存命中率会很低。7.3 与业务系统的解耦建议kkfileview 最好作为独立服务不要和业务系统混部。业务系统通过 HTTP 调用不直接依赖它的 jar 包。这样升级、扩容、排障都互不影响。文件存储也解耦业务系统把文件存到对象存储kkfileview 只负责预览。预览链接由业务后端生成前端只负责 iframe 展示。如果要做权限控制可以在业务后端生成一次性预览 tokenkkfileview 前面加一层网关校验 token。或者把文件 URL 做成带时效的签名 URLkkfileview 请求时校验签名。这样既安全又不用改 kkfileview 源码。我现在的做法是业务后端生成预览链接链接里带一个短效 tokenNginx 的 Lua 脚本校验 token 后转发到 kkfileview。这样 kkfileview 完全不感知权限维护简单。最后分享一个我个人用了很久的部署习惯Docker 镜像固定版本配置文件挂载并纳入 Git字体提前打进镜像Redis 必开Nginx 加超时和限流定时清理临时文件。这套组合跑了两年除了偶尔升级 LibreOffice基本没出过大事。kkfileview 不是银弹但在这个需求区间里它确实能帮你省下大量造轮子的时间。如果你准备上生产先把字体和时区搞定再调缓存和并发最后加安全和监控基本就稳了。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门