文章目录
- Java Word转PDF文件方案评测
- 一、kkFileView应用场景一:官网原始部署与应用
- 二、kkFileView应用场景二:编译、自定义制作docker镜像部署
- 三、kkfileview预览pdf文件以及关键词高亮和定位
Java Word转PDF文件方案评测
Word转PDF网上常见的方案5种,aspose-words、docx4j、openoffice、poi、spire.doc。
方案对比说明
提示:上面方案仅限于Windows操作系统,Linux OS实测Word转换PDF时,docx4j会报错、poi 文档内容会出现乱码(应该是系统需要安装font字体)。
基于项目环境是Linux Os,最终放弃上面所有方案,选择Apache协议开源的kkFileView,官网
kkFileView为文件文档在线预览项目解决方案,对标业内付费产品有【永中office】【office365】【idocv】等,Apache协议开源项目,该项目使用流行的spring boot搭建,易上手和部署,基本支持主流办公文档的在线预览,如doc,docx,Excel,pdf,txt,zip,rar,图片等。
以下篇幅将介绍 kkFileView开源项目的不同的应用场景。
一、kkFileView应用场景一:官网原始部署与应用
-
环境要求 #
Java: 1.8+
LibreOffice或OpenOffice(Windows下已内置,CentOS或Ubuntu下会自动下载安装,MacOS下需要自行安装) -
物理机或虚拟机上运行 #
1)从 码云发行版本 下载最新版发行包
项目目录说明:
Docker目录:构建kkFileView JDK环境和Docker制作文件,Docker制作文件(Dockerfile)执行操作:
1)引入ubuntu:20.04
2)内置一些常用中文字体
3)安装language-pack-zh*
4)下载kkview.cn官网server-jre-8u251-linux-x64.tar.gz 即jdk1.8环境
5)安装 libreoffice
6)清理临时文件
7)设置JDK、Lang等配置和CMD命令
Server目录:kkFileView 服务目录
lib:第三方转码jar包
LibreOfficePortable:LibreOffice 便携版,存放LibreOffice关联的环境文件
src:kkFileView 后台服务源代码
Target:kkFileView 后台服务编译后生成可执行包(kkFileView-4.4.0-SNAPSHOT.jar、.tar.gz、.zip等)
pom.xml文件:服务MVN构建文件
2)Idea开发工具 重新执行mvn命令,编译kkFileView服务
3)解压kkFileView-x.x.x文件(Windows用.zip包,Linux/MacOS用.tar.gz包)
打开解压后文件夹的bin目录,运行startup脚本(Windows下以管理员身份运行startup.bat,Linux以root用户运行startup.sh)
4)打开浏览器访问本机8012端口 http://127.0.0.1:8012 即可看到项目演示用首页
- Docker上运行 #
拉取镜像 #
docker pull keking/kkfileview:4.1.0
#网络环境不方便访问Docker中央仓库
wget http://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
浏览器访问容器8012端口 http://127.0.0.1:8012 即可看到项目演示用首页
- 项目接入使用
当您的项目内需要预览文件时,只需要调用浏览器打开本项目的预览接口,并传入须要预览文件的url,示例如下:
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/js-base64@3.6.0/base64.min.js"></script>
var url = 'http://127.0.0.1:8080/file/test.txt'; //要预览文件的访问地址
window.open('http://127.0.0.1:8012/onlinePreview?url='+encodeURIComponent(Base64.encode(previewUrl)));
二、kkFileView应用场景二:编译、自定义制作docker镜像部署
前提:安装docker
1)Idea开发工具 重新执行mvn命令,编译kkFileView服务,最终生成kkFileView-4.4.0-SNAPSHOT.tar.gz
2)服务器端(linux主机)编写Docerfile、构建、运行
创建merakkkfileview目录、上传Dockerfile和kkFileView-4.4.0-SNAPSHOT.tar.gz
[root@iZm5e1mrbokrl04np8nv1mZ merakkkfileview]# mkdir merakkkfileview
[root@iZm5e1mrbokrl04np8nv1mZ merakkkfileview]# pwd
/home/merak/merakkkfileview
[root@iZm5e1mrbokrl04np8nv1mZ merakkkfileview]# ll
total 291960
-rw-r--r-- 1 root root 371 Aug 23 16:35 Dockerfile
-rw-r--r-- 1 root root 298959899 Aug 23 16:34 kkFileView-4.4.0-SNAPSHOT.tar.gz
编辑Dockerfile文件
[root@iZm5e1mrbokrl04np8nv1mZ merakkkfileview]# cat Dockerfile
FROM keking/kkfileview-jdk:latest
MAINTAINER chenjh "842761733@qq.com"
ADD ./kkFileView-*.tar.gz /opt/
ENV KKFILEVIEW_BIN_FOLDER /opt/kkFileView-4.4.0-SNAPSHOT/bin
ENTRYPOINT ["java","-Dfile.encoding=UTF-8","-Dspring.config.location=/opt/kkFileView-4.4.0-SNAPSHOT/config/application.properties","-jar","/opt/kkFileView-4.4.0-SNAPSHOT/bin/kkFileView-4.4.0-SNAPSHOT.jar"]
构建和查询构建镜像
[root@iZm5e1mrbokrl04np8nv1mZ]# docker build -t merakkkfileview:1.0 .
[root@iZm5e1mrbokrl04np8nv1mZ]# docker images | grep merakkkfileview
merakkkfileview 1.0 ebdf069b5ece 33 minutes ago 1.65GB
运行Docker
[root@iZm5e1mrbokrl04np8nv1mZ]# docker run -itd -p 11182:8012 merakkkfileview:1.0
将Docker内kkfileview默认端口8012映射成外部端口11182
检查是否正常
[root@iZm5e1mrbokrl04np8nv1mZ ]# docker ps | grep merakkkfileview
5da1a5c602ff merakkkfileview:1.0 "java -Dfile.encodin…" 28 minutes ago Up 28 minutes 0.0.0.0:11182->8012/tcp, :::11182->8012/tcp
3)首页访问与测试 http://ip:11182/
三、kkfileview预览pdf文件以及关键词高亮和定位
1、kkfileview源代码前后端代码改造
kkfileview通过OnlinePreviewController.java业务类@GetMapping( “/onlinePreview”)接口实现文件的在线浏览。
onlinePreview接口:url参数获取原始文件路径 ; Model :Model层接收数据且向View层渲染数据;HttpServletRequest:接收前端浏览器请求信息。
所以我们需要增加参数keyword:接收前台高亮搜索的关键词。
/**
* 文件在线浏览
* @param url 原始文件路径
* @param keyword 接收前台高亮搜索的关键词
* @param model Model层接收数据且向View层渲染数据
* @param req 接收前端浏览器请求信息
* @return
*/
@GetMapping( "/onlinePreview")
public String onlinePreview(String url, String keyword, Model model, HttpServletRequest req) {
String fileUrl;
try {
fileUrl = WebUtils.decodeUrl(url);
} catch (Exception ex) {
String errorMsg = String.format(BASE64_DECODE_ERROR_MSG, "url");
return otherFilePreview.notSupportedFile(model, errorMsg);
}
FileAttribute fileAttribute = fileHandlerService.getFileAttribute(fileUrl, req);
model.addAttribute("file", fileAttribute);
model.addAttribute("keyword", keyword); // 将接收前台高亮搜索的关键词存储到model中
FilePreview filePreview = previewFactory.get(fileAttribute);
logger.info("预览文件url:{},previewType:{}", fileUrl, fileAttribute.getType());
return filePreview.filePreviewHandle(fileUrl, model, fileAttribute);
}
web/pdf.ftl文件 获取关键词,传递给pdf.js,pdf.ftl文件:
<script type="text/javascript">
var url = '${finalUrl}';
var baseUrl = '${baseUrl}'.endsWith('/') ? '${baseUrl}' : '${baseUrl}' + '/';
if (!url.startsWith(baseUrl)) {
url = baseUrl + 'getCorsFile?urlPath=' + encodeURIComponent(Base64.encode(url));
}
// 首先从我们的model中获取keyword
var keyword = '${keyword}';
document.getElementsByTagName('iframe')[0].src = "${baseUrl}pdfjs/web/viewer.html?file=" + encodeURIComponent(url) + "&disablepresentationmode=${pdfPresentationModeDisable}&disableopenfile=${pdfOpenFileDisable}&disableprint=${pdfPrintDisable}&disabledownload=${pdfDownloadDisable}&disablebookmark=${pdfBookmarkDisable}&disableediting=${pdfDisableEditing}" + "&keyword="+ keyword;
document.getElementsByTagName('iframe')[0].height = document.documentElement.clientHeight - 10;
static/pdfjs/viewer.js文件,修改 setInitialView(storedHash) {} 内置函数:
setInitialView(storedHash) {
//原始代码----开始
let {
rotation,
sidebarView,
scrollMode,
spreadMode
} = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
const setRotation = angle => {
if ((0, _ui_utils.isValidRotation)(angle)) {
this.pdfViewer.pagesRotation = angle;
}
};
const setViewerModes = (scroll, spread) => {
if ((0, _ui_utils.isValidScrollMode)(scroll)) {
this.pdfViewer.scrollMode = scroll;
}
if ((0, _ui_utils.isValidSpreadMode)(spread)) {
this.pdfViewer.spreadMode = spread;
}
};
this.isInitialViewSet = true;
this.pdfSidebar?.setInitialView(sidebarView);
setViewerModes(scrollMode, spreadMode);
if (this.initialBookmark) {
setRotation(this.initialRotation);
delete this.initialRotation;
this.pdfLinkService.setHash(this.initialBookmark);
this.initialBookmark = null;
} else if (storedHash) {
setRotation(rotation);
this.pdfLinkService.setHash(storedHash);
}
this.toolbar?.setPageNumber(this.pdfViewer.currentPageNumber, this.pdfViewer.currentPageLabel);
this.secondaryToolbar?.setPageNumber(this.pdfViewer.currentPageNumber);
if (!this.pdfViewer.currentScaleValue) {
this.pdfViewer.currentScaleValue = _ui_utils.DEFAULT_SCALE_VALUE;
}
//原始代码----结束
//高亮需要加入的代码:获取keyword、回写以及触发高亮点击按钮
const queryString = document.location.search.slice(1);
const m = /(^|&)keyword=([^&]*)/.exec(queryString);
const keyword = m ? decodeURIComponent(m[2]) : "";
console.log("keyword", keyword);
//对查询输入框进行赋值
document.getElementById("findInput").value=keyword;
//点击高亮按钮实现高亮显示关键词
document.getElementById("findHighlightAll").click();*
},
2.重新编译、自定义制作docker镜像部(具体过程同“kkFileView应用场景二:编译、自定义制作docker镜像部署”一致。
3.运行效果:
PS
kkfileview官网
kkfileview文档
gitee源码
kkfileview配置-server\src\main\config\application.properties:
#######################################不可动态配置,需要重启生效#######################################
server.port = ${KK_SERVER_PORT:11182}
server.servlet.context-path= ${KK_CONTEXT_PATH:/}
server.servlet.encoding.charset = utf-8
#启用GZIP压缩功能
server.compression.enable= true
#允许压缩的响应缓冲区最小字节数,默认2048
server.compression.min-response-size = 2048
#压缩格式
server.compression.mime-types=application/javascript,text/css,application/json,application/xml,text/html,text/xml,text/plain,font/woff,application/font-woff,font/eot,image/svg+xml,image/x-icon
# 文件上传限制前端
spring.servlet.multipart.max-file-size=500MB
#文件上传限制
spring.servlet.multipart.max-request-size=500MB
## Freemarker 配置
spring.freemarker.template-loader-path = classpath:/web/
spring.freemarker.cache = false
spring.freemarker.charset = UTF-8
spring.freemarker.check-template-location = true
spring.freemarker.content-type = text/html
spring.freemarker.expose-request-attributes = true
spring.freemarker.expose-session-attributes = true
spring.freemarker.request-context-attribute = request
spring.freemarker.suffix = .ftl
# office设置
#openoffice或LibreOffice home路径
#office.home = C:\\Program Files (x86)\\OpenOffice 4
office.home = ${KK_OFFICE_HOME:default}
## office转换服务的进程数,默认开启两个进程
office.plugin.server.ports = 2001,2002
## office 转换服务 task 超时时间,默认五分钟
office.plugin.task.timeout = 5m
#生成限制 默认不限制 使用方法 (1-5)
office.pagerange = ${KK_OFFICE_PAGERANGE:false}
#生成水印 默认不启用 使用方法 (kkFileView)
office.watermark = ${KK_OFFICE_WATERMARK:false}
#OFFICE JPEG图片压缩
office.quality = ${KK_OFFICE_QUALITY:80}
#图像分辨率限制
office.maximageresolution = ${KK_OFFICE_MAXIMAGERESOLUTION:150}
#导出书签
office.exportbookmarks = ${KK_OFFICE_EXPORTBOOKMARKS:true}
#批注作为PDF的注释
office.exportnotes = ${KK_OFFICE_EXPORTNOTES:true}
#加密文档 生成的PDF文档 添加密码(密码为加密文档的密码)
office.documentopenpasswords = ${KK_OFFICE_DOCUMENTOPENPASSWORD:true}
#xlsx格式前端解析
office.type.web = ${KK_OFFICE_TYPE_WEB:web}
# 其他核心设置
#预览生成资源路径(默认为打包根路径下的file目录下)
#file.dir = D:\\kkFileview\\
file.dir = ${KK_FILE_DIR:default}
#允许预览的本地文件夹 默认不允许任何本地文件被预览
#WINDOWS参考 local.preview.dir = \D:\\kkFileview\\1\\1.txt (注意前面必须添加反斜杠)
#LINUX参考 local.preview.dir = /opt/1.txt (注意前面必须是正斜杠)
#使用方法 windows file://d:/1/1.txt linux file:/opt/1/1.txt
#file 协议参考:https://datatracker.ietf.org/doc/html/rfc8089
local.preview.dir = ${KK_LOCAL_PREVIEW_DIR:default}
#是否启用缓存
cache.enabled = ${KK_CACHE_ENABLED:true}
#缓存实现类型,不配默认为内嵌RocksDB(type = default)实现,可配置为redis(type = redis)实现(需要配置spring.redisson.address等参数)和 JDK 内置对象实现(type = jdk),
cache.type = ${KK_CACHE_TYPE:jdk}
#redis连接,只有当cache.type = redis时才有用
spring.redisson.address = ${KK_SPRING_REDISSON_ADDRESS:127.0.0.1:6379}
spring.redisson.password = ${KK_SPRING_REDISSON_PASSWORD:}
#缓存是否自动清理 true 为开启,注释掉或其他值都为关闭
cache.clean.enabled = ${KK_CACHE_CLEAN_ENABLED:true}
#缓存自动清理时间,cache.clean.enabled = true时才有用,cron表达式,基于Quartz cron
cache.clean.cron = ${KK_CACHE_CLEAN_CRON:0 0 3 * * ?}
#######################################可在运行时动态配置#######################################
#提供预览服务的地址,默认从请求url读,如果使用nginx等反向代理,需要手动设置
#base.url = https://file.keking.cn
base.url = ${KK_BASE_URL:default}
#信任站点,多个用','隔开,设置了之后,会限制只能预览来自信任站点列表的文件,默认不限制
#trust.host = kkview.cn
trust.host = ${KK_TRUST_HOST:default}
#文本类型,默认如下,可自定义添加
simText = ${KK_SIMTEXT:txt,html,htm,asp,jsp,xml,json,properties,md,gitignore,log,java,py,c,cpp,sql,sh,bat,m,bas,prg,cmd}
#FTP模块设置
#预览源为FTP时 FTP用户名,可在ftp url后面加参数ftp.username=ftpuser指定,不指定默认用配置的
ftp.username = ${KK_FTP_USERNAME:ftpuser}
#预览源为FTP时 FTP密码,可在ftp url后面加参数ftp.password=123456指定,不指定默认用配置的
ftp.password = ${KK_FTP_PASSWORD:123456}
#预览源为FTP时, FTP连接默认ControlEncoding(根据FTP服务器操作系统选择,Linux一般为UTF-8,Windows一般为GBK),可在ftp url后面加参数ftp.control.encoding=UTF-8指定,不指定默认用配置的
ftp.control.encoding = ${KK_FTP_CONTROL_ENCODING:UTF-8}
#视频设置
#多媒体类型,默认如下,可自定义添加
media = ${KK_MEDIA:mp3,wav,mp4,flv}
#是否开启多媒体类型转视频格式转换,目前可转换视频格式有:avi,mov,wmv,3gp,rm
#请谨慎开启此功能,建议异步调用添加到处理队列,并且增加任务队列处理线程,防止视频转换占用完线程资源,转换比较耗费时间,并且控制了只能串行处理转换任务
media.convert.disable = ${KK_MEDIA_CONVERT_DISABLE:false}
#支持转换的视频类型
convertMedias = ${KK_CONVERTMEDIAS:avi,mov,wmv,mkv,3gp,rm}
#PDF预览模块设置
#配置PDF文件生成图片的像素大小,dpi 越高,图片质量越清晰,同时也会消耗更多的计算资源。
pdf2jpg.dpi = ${KK_PDF2JPG_DPI:144}
#是否禁止演示模式
pdf.presentationMode.disable = ${KK_PDF_PRESENTATION_MODE_DISABLE:true}
#是否禁止打开文件
pdf.openFile.disable = ${KK_PDF_OPEN_FILE_DISABLE:true}
#是否禁止打印转换生成的pdf文件
pdf.print.disable = ${KK_PDF_PRINT_DISABLE:true}
#是否禁止下载转换生成的pdf文件
pdf.download.disable = ${KK_PDF_DOWNLOAD_DISABLE:true}
#是否禁止bookmark
pdf.bookmark.disable = ${KK_PDF_BOOKMARK_DISABLE:true}
#是否禁止签名
pdf.disable.editing = ${KK_PDF_DISABLE_EDITING:false}
#office类型文档(word ppt)样式,默认为图片(image),可配置为pdf(预览时也有按钮切换)
office.preview.type = ${KK_OFFICE_PREVIEW_TYPE:image}
#是否关闭office预览切换开关,默认为false,可配置为true关闭
office.preview.switch.disabled = ${KK_OFFICE_PREVIEW_SWITCH_DISABLED:false}
#水印内容
#例:watermark.txt = ${WATERMARK_TXT:凯京科技内部文件,严禁外泄}
#如需取消水印,内容设置为空即可,例:watermark.txt = ${WATERMARK_TXT:}
watermark.txt = ${WATERMARK_TXT:}
#水印x轴间隔
watermark.x.space = ${WATERMARK_X_SPACE:10}
#水印y轴间隔
watermark.y.space = ${WATERMARK_Y_SPACE:10}
#水印字体
watermark.font = ${WATERMARK_FONT:微软雅黑}
#水印字体大小
watermark.fontsize = ${WATERMARK_FONTSIZE:18px}
#水印字体颜色
watermark.color = ${WATERMARK_COLOR:black}
#水印透明度,要求设置在大于等于0.005,小于1
watermark.alpha = ${WATERMARK_ALPHA:0.2}
#水印宽度
watermark.width = ${WATERMARK_WIDTH:180}
#水印高度
watermark.height = ${WATERMARK_HEIGHT:80}
#水印倾斜度数,要求设置在大于等于0,小于90
watermark.angle = ${WATERMARK_ANGLE:10}
#首页功能设置
#是否禁用首页文件上传
file.upload.disable = ${KK_FILE_UPLOAD_ENABLED:false}
# 备案信息,默认为空
beian = ${KK_BEIAN:default}
#禁止上传类型
prohibit = ${KK_PROHIBIT:exe,dll,dat}
#启用验证码删除文件 默认关闭
delete.captcha= ${KK_DELETE_CAPTCHA:false}
#删除密码
delete.password = ${KK_DELETE_PASSWORD:123456}
#删除 转换后OFFICE、CAD、TIFF、压缩包源文件 默认开启 节约磁盘空间
delete.source.file = ${KK_DELETE_SOURCE_FILE:true}
#Tif类型设置
#Tif类型图片浏览模式:tif(利用前端js插件浏览);jpg(转换为jpg后前端显示);pdf(转换为pdf后显示,便于打印)
tif.preview.type = ${KK_TIF_PREVIEW_TYPE:tif}
#Cad类型设置
#Cad类型图片浏览模式:tif(利用前端js插件浏览);svg(转换为svg显示);pdf(转换为pdf后显示,便于打印)
cad.preview.type = ${KK_CAD_PREVIEW_TYPE:svg}
#Cad转换超时设置
cad.timeout =${KK_CAD_TIMEOUT:90}
#Cad转换线程设置
cad.thread =${KK_CAD_THREAD:5}