Compare commits

...

55 Commits

Author SHA1 Message Date
陈精华
eb12eb0695 4.1.0版本发布 2022-12-14 09:45:48 +08:00
陈精华
d78351f72c NULL地址不允许预览 2022-12-14 09:40:37 +08:00
陈精华
af752cfa13 修复Autowire static method 2022-12-13 18:17:20 +08:00
陈精华
f0dc845825 禁止TRACE请求 2022-12-13 18:04:22 +08:00
陈精华
5ecb5f667d 懒加载同时加载水印 2022-12-13 17:56:35 +08:00
陈精华
3dcd183171 ofd和tiff下载跨域文件接口修改 2022-12-13 17:50:28 +08:00
陈精华
167189d4e4 xml预览加上bootstrap样式 2022-12-13 17:26:50 +08:00
陈精华
d6c083fb5b 更新Office和Image文件类型 2022-12-13 17:04:40 +08:00
陈精华
1dd59cf764 更新跨域文件下载方法 2022-12-13 17:04:34 +08:00
陈精华
e7930a2442 更新tiff预览 2022-12-13 17:04:24 +08:00
陈精华
1261e6aa03 部分PDF转image报错问题修复 2022-12-13 17:04:16 +08:00
陈精华
3abcfe90bc XML文本转义 2022-12-13 17:04:09 +08:00
陈精华
cf336781d8 ODF预览组件更新 2022-12-13 17:04:00 +08:00
陈精华
4c0aa3cfc3 更新jQuery版本到3.6.1 2022-12-13 17:02:03 +08:00
陈精华
0a1fb6d983 commonHeader移除bootstrap依赖 2022-12-13 11:16:10 +08:00
陈精华
99b1f83e50 PPT预览水印 2022-12-13 09:53:28 +08:00
陈精华
4db74d0931 更新Gitee流水线脚本 2022-12-12 17:48:02 +08:00
陈精华
9860df9b6d ppt预览水印 2022-12-12 17:40:36 +08:00
陈精华
4c225b030d 修复压缩文件中文乱码 2022-12-12 16:49:41 +08:00
陈精华
9e5b9d4889 解决编译warning 2022-12-12 14:23:32 +08:00
陈精华
e9c4e134c6 修复文本文档以'~'结尾报错 2022-12-12 10:30:13 +08:00
陈精华
5704a4182e 更新Docker镜像为阿里云源 2022-12-08 16:00:32 +08:00
陈精华
489bdfbc01 csv当作excel预览 2022-12-08 13:43:01 +08:00
Bo_boom
53a840af4b 表单校验警告提示添加; (#410)
* 表单校验警告提示添加

Co-authored-by: wusongda <wusongda@keking.cn>
2022-12-05 17:38:33 +08:00
wsd7747
8c8d596c43 预览演示首页重构 (#403)
bootstrap3更新
首页重构
Co-authored-by: wusongda <wusongda@keking.cn>
2022-11-21 15:01:19 +08:00
陈精华
a3f91641dd 依赖调整 2022-11-18 23:30:43 +08:00
gitchenjh
f5754be9ff Merge pull request #401 from gitchenjh/master
Linux发行版&Docker镜像升级LibreOffice7.3、其他优化
2022-11-15 10:08:52 +08:00
陈精华
12f40b831f 更新首页说明 2022-11-14 10:50:27 +08:00
陈精华
859feff328 Docker基础镜像默认安装LibreOffice7.3 2022-11-14 09:17:05 +08:00
陈精华
bba44ca057 Linux下检测正在运行的office进程检测逻辑修正 2022-11-11 17:06:42 +08:00
陈精华
5134f7a121 Linux环境下默认安装LibreOffice7.3, 检测Office组件新增LibreOffice 7.3 7.4 版本 2022-11-11 17:00:51 +08:00
陈精华
b366d0b464 首页预览增加是否合法url判断 2022-11-11 17:00:51 +08:00
陈精华
e3fb1d7c15 更新banner 2022-11-11 17:00:50 +08:00
陈精华
883b45f201 中文URL参数解码 2022-11-11 17:00:50 +08:00
gitchenjh
8fb32e4f73 Merge pull request #400 from gitchenjh/master
修复升级poi版本后判断office是否受密码保护方法
2022-11-11 10:53:33 +08:00
陈精华
764ea702d0 修复升级poi版本后判断office是否受密码保护方法 2022-11-10 18:27:39 +08:00
kl
b225cebc95 更新相关依赖版本 (#377) 2022-08-01 15:10:30 +08:00
kl
106036d989 优化 baseURL 的获取逻辑 (#376) 2022-08-01 14:09:41 +08:00
kischn.sun
026656711d 添加通过 http header X-Base-Url 来动态传入 baseUrl 的功能 (#252)
* 将 baseUrl 拼接挪到 else 分支下消除特殊情况下(不走else)不必要的拼接处理

* 添加通过 Http Header X-Base-Url 来动态赋值 baseUrl 的功能来实现更灵活代理支持
2022-08-01 14:01:04 +08:00
gkchp
35a8c4a5a6 修复加号被转换成空格导致Base64解码出错 (#340)
* 修复url中加号被替换为空格导致的Base64解码出错

* Base64解码抽象到工具类

* #340 补充注释
2022-07-29 23:08:21 +08:00
kl
86960e3813 Fix #370 2022-07-25 18:33:57 +08:00
kl
b099d52520 优化、精简代码。使用 @GetMapping、@PostMapping 替换 @RequestMapping 2022-07-25 17:28:26 +08:00
shenghuadun
6efe15788c !43 水印其他属性不知道动态传入的问题
* 水印除文本外其他属性可通过url动态传入
2022-07-21 06:45:46 +00:00
tomhusky
3e43c2f9d0 !49 修复Linux环境中OfficePluginManager中KillProcess出现杀掉进程失败,导致二次启动失败的bug
* 修复Linux环境中OfficePluginManager中KillProcess出现杀掉已经存在进程失败,导致二次启动失败的bug
2022-07-21 03:50:09 +00:00
陈精华
f1b949865f 更新Gitee workflow文件 2022-07-21 11:38:48 +08:00
陈精华
ab439a17a3 所有页面增加favicon.ico 2022-07-21 11:29:54 +08:00
陈精华
dd65564af6 修复getCorsFile接口未加base64编码(filter中解码异常) 2022-07-21 11:27:06 +08:00
yl-yue
acffcbfe98 !51 实现预览加密的(受密码保护)office文件
* 1. 修复getCorsFile接口高危安全漏洞
* 1. 优化密码错误提示(“密码错误,请重新输入密码。”)
* 1. 修复PPT重复预览bug,此bug导致ppt每次预览会执行两次转换(请求两次onlinePreview接口),在大文件尤其耗时(双倍时…
* 1. 【加密office预览】优化受密码保护的office文件检查逻辑,提升旧文件格式的兼容性
* 1. 【加密office预览】优化office文件是否受密码保护判断逻辑,避免兼容性误判
* 1. 【加密office预览】优化重新输入密码提示。
* 1. 【加密office预览】优化当密码输入错误后,不是抛出异常,而是提示用户重新输入
* 1. 优化prompt提示框的输入密码提示样式
* 1. 实现基于userToken缓存加密文件,没有userToken的加密文件不缓存
* 1. 优化docker构建方案,使用分层构建方式,采用层级缓存解决构建慢发布慢等问题。从原本5分钟左右缩短至几秒
* 1. 加密文件暂时不缓存(后续基于用户token实现,基于用户缓存)
* 1. 优化office文件下载逻辑,跳过重复下载(大量节约带宽与磁盘空间)。
* 1. 修复预览不同类型的加密office文件bug
* 实现预览加密的(受密码保护)office文件
2022-07-21 03:19:46 +00:00
kailing
04703aa03c add pipeline-20220716.yml for Gitee Go created_at:2022-07-16 12:57:59 2022-07-16 12:57:59 +00:00
kailing
584e6b2c77 add default pipeline template yaml 2022-07-16 12:56:45 +00:00
chenkailing
82f6d3565f 优化 file:// 协议访问授信目录的代码结构 2022-05-25 19:37:29 +08:00
gitchenjh
8c68834e17 Merge pull request #342 from gitchenjh/master
修复使用http文件流下载时文件名编码异常Gitee-#I4W0TQ
2022-03-09 19:48:22 -06:00
陈精华
ba7b6eed4a 修复使用http文件流下载时文件名编码异常Gitee-#I4W0TQ 2022-03-10 09:47:05 +08:00
gitchenjh
051ad0f4ea Merge pull request #334 from NullXin/wzxdev
ppt显示问题
2022-02-21 00:10:17 -06:00
1192247166@qq.com
05935c29e1 1、左边侧边栏显示总页码显示为0
2、修改左屏幕分辨率过高,显示图片过大。
2022-01-26 11:38:12 +08:00
116 changed files with 49633 additions and 11121 deletions

1
.gitignore vendored
View File

@@ -25,6 +25,7 @@ nbdist/
### VS Code ###
.vscode/
.DS_Store
server/src/main/cache/
server/src/main/file/

View File

@@ -0,0 +1,31 @@
version: '1.0'
name: master-pipeline
displayName: MasterPipeline
stages:
- stage:
name: compile
displayName: 编译
steps:
- step: build@maven
name: build_maven
displayName: Maven 构建
# 支持67891011六个版本
jdkVersion: 8
# 支持2.2.13.2.53.3.93.5.23.5.33.5.43.6.13.6.3八个版本
mavenVersion: 3.6.3
# 构建命令
commands:
- mvn -B clean package -Dmaven.test.skip=true
# 非必填字段开启后表示将构建产物暂存但不会上传到制品库中7天后自动清除
artifacts:
# 构建产物名字作为产物的唯一标识可向下传递支持自定义默认为BUILD_ARTIFACT在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
- name: BUILD_ARTIFACT
# 构建产物获取路径是指代码编译完毕之后构建物的所在路径如通常jar包在target目录下当前目录为代码库根目录
path:
- ./server/target/kkFileView-*.tar.gz
- ./server/target/kkFileView-*.zip
triggers:
push:
branches:
include:
- master

View File

@@ -1,42 +1,5 @@
FROM ubuntu:20.04
FROM keking/kkfileview-jdk:4.1.1
MAINTAINER chenjh "842761733@qq.com"
ADD server/target/kkFileView-*.tar.gz /opt/
COPY fonts/* /usr/share/fonts/chinese/
RUN echo "deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse\ndeb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse\ndeb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse\ndeb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse\ndeb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse\ndeb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse\ndeb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse\ndeb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse\ndeb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse\ndeb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse" > /etc/apt/sources.list &&\
apt-get clean && apt-get update &&\
apt-get install -y locales && apt-get install -y language-pack-zh-hans &&\
localedef -i zh_CN -c -f UTF-8 -A /usr/share/locale/locale.alias zh_CN.UTF-8 && locale-gen zh_CN.UTF-8 &&\
export DEBIAN_FRONTEND=noninteractive &&\
apt-get install -y tzdata && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime &&\
apt-get install -y libxrender1 && apt-get install -y libxt6 && apt-get install -y libxext-dev && apt-get install -y libfreetype6-dev &&\
apt-get install -y wget && apt-get install -y ttf-mscorefonts-installer && apt-get install -y fontconfig &&\
apt-get install ttf-wqy-microhei &&\
apt-get install ttf-wqy-zenhei &&\
apt-get install xfonts-wqy &&\
cd /tmp &&\
wget https://kkfileview.keking.cn/server-jre-8u251-linux-x64.tar.gz &&\
tar -zxf /tmp/server-jre-8u251-linux-x64.tar.gz && mv /tmp/jdk1.8.0_251 /usr/local/ &&\
# 安装 OpenOffice
# wget https://kkfileview.keking.cn/Apache_OpenOffice_4.1.6_Linux_x86-64_install-deb_zh-CN.tar.gz -cO openoffice_deb.tar.gz &&\
# tar -zxf /tmp/openoffice_deb.tar.gz && cd /tmp/zh-CN/DEBS &&\
# dpkg -i *.deb && dpkg -i desktop-integration/openoffice4.1-debian-menus_4.1.6-9790_all.deb &&\
# 安装 libreoffice
apt-get install -y libxinerama1 libcairo2 libcups2 libx11-xcb1 &&\
wget https://kkfileview.keking.cn/LibreOffice_7.1.4_Linux_x86-64_deb.tar.gz -cO libreoffice_deb.tar.gz &&\
tar -zxf /tmp/libreoffice_deb.tar.gz && cd /tmp/LibreOffice_7.1.4.2_Linux_x86-64_deb/DEBS &&\
dpkg -i *.deb &&\
rm -rf /tmp/* && rm -rf /var/lib/apt/lists/* &&\
cd /usr/share/fonts/chinese &&\
mkfontscale &&\
mkfontdir &&\
fc-cache -fv
ENV JAVA_HOME /usr/local/jdk1.8.0_251
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV PATH $PATH:$JAVA_HOME/bin
ENV LANG zh_CN.UTF-8
ENV LC_ALL zh_CN.UTF-8
ENV KKFILEVIEW_BIN_FOLDER /opt/kkFileView-4.1.0-SNAPSHOT/bin
ENTRYPOINT ["java","-Dfile.encoding=UTF-8","-Dspring.config.location=/opt/kkFileView-4.1.0-SNAPSHOT/config/application.properties","-jar","/opt/kkFileView-4.1.0-SNAPSHOT/bin/kkFileView-4.1.0-SNAPSHOT.jar"]
ENV KKFILEVIEW_BIN_FOLDER /opt/kkFileView-4.1.0/bin
ENTRYPOINT ["java","-Dfile.encoding=UTF-8","-Dspring.config.location=/opt/kkFileView-4.1.0/config/application.properties","-jar","/opt/kkFileView-4.1.0/bin/kkFileView-4.1.0.jar"]

View File

@@ -110,6 +110,19 @@ pdf预览模式预览效果如下
### 历史更新记录
> 2022年12月14日v4.1.0 版本发布
1. 全新首页视觉 @wsd7747
2. tif图片预览兼容多页tif的pdf转换jpg转换以及jpg在线多页预览功能 @zhangzhen1979
3. 优化docker构建方案使用分层构建方式 @yl-yue
4. 实现基于userToken缓存加密文件 @yl-yue
5. 实现加密wordpptexcel文件预览 @yl-yue
6. Linux & Docker镜像升级LibreOffice 7.3
7. 更新OFD预览组件更新tif预览组件更新PPT水印支持
8. 大量其他升级优化 & 已知问题修复
感谢 @yl-yue @wsd7747 @zhangzhen1979 @tomhusky @shenghuadun @kischn.sun 的代码贡献
> 2021年7月6日v4.0.0 版本发布
1. 底层集成OpenOffice替换为LibreOfficeOffice文件兼容性增强预览效果提升

View File

@@ -0,0 +1,38 @@
FROM ubuntu:20.04
MAINTAINER chenjh "842761733@qq.com"
# 内置一些常用的中文字体,避免普遍性乱码
COPY fonts/* /usr/share/fonts/chinese/
RUN apt-get clean && apt-get update &&\
sed -i 's/http:\/\/archive.ubuntu.com/https:\/\/mirrors.aliyun.com/g' /etc/apt/sources.list &&\
sed -i 's/# deb/deb/g' /etc/apt/sources.list &&\
apt-get install -y --reinstall ca-certificates &&\
apt-get clean && apt-get update &&\
apt-get install -y locales language-pack-zh-hans &&\
localedef -i zh_CN -c -f UTF-8 -A /usr/share/locale/locale.alias zh_CN.UTF-8 && locale-gen zh_CN.UTF-8 &&\
export DEBIAN_FRONTEND=noninteractive &&\
apt-get install -y tzdata && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime &&\
apt-get install -y fontconfig ttf-mscorefonts-installer ttf-wqy-microhei ttf-wqy-zenhei xfonts-wqy &&\
apt-get install -y wget &&\
cd /tmp &&\
wget https://kkfileview.keking.cn/server-jre-8u251-linux-x64.tar.gz &&\
tar -zxf /tmp/server-jre-8u251-linux-x64.tar.gz && mv /tmp/jdk1.8.0_251 /usr/local/ &&\
# 安装 libreoffice
apt-get install -y libxrender1 libxinerama1 libxt6 libxext-dev libfreetype6-dev libcairo2 libcups2 libx11-xcb1 libnss3 &&\
wget https://kkfileview.keking.cn/LibreOffice_7.3.7_Linux_x86-64_deb.tar.gz -cO libreoffice_deb.tar.gz &&\
tar -zxf /tmp/libreoffice_deb.tar.gz && cd /tmp/LibreOffice_7.3.7.2_Linux_x86-64_deb/DEBS &&\
dpkg -i *.deb &&\
# 清理临时文件
rm -rf /tmp/* && rm -rf /var/lib/apt/lists/* &&\
cd /usr/share/fonts/chinese &&\
mkfontscale &&\
mkfontdir &&\
fc-cache -fv
ENV JAVA_HOME /usr/local/jdk1.8.0_251
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV PATH $PATH:$JAVA_HOME/bin
ENV LANG zh_CN.UTF-8
ENV LC_ALL zh_CN.UTF-8
CMD ["/bin/bash"]

View File

@@ -0,0 +1,2 @@
# 执行如下命令构建基础镜像加快kkfileview docker镜像构建与发布
docker build --tag keking/kkfileview-jdk:4.1.1 .

View File

@@ -3,11 +3,10 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>kkFileView-parent</artifactId>
<groupId>cn.keking</groupId>
<version>4.1.0-SNAPSHOT</version>
<version>4.1.0</version>
</parent>
<artifactId>office-plugin</artifactId>
@@ -27,19 +26,9 @@
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.openoffice</groupId>
<artifactId>juh</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>org.openoffice</groupId>
<artifactId>ridl</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>org.openoffice</groupId>
<artifactId>unoil</artifactId>
<version>3.2.1</version>
<groupId>org.libreoffice</groupId>
<artifactId>libreoffice</artifactId>
<version>7.1.4</version>
</dependency>
<dependency>
<!-- for the command line tool -->
@@ -72,6 +61,7 @@
<plugins>
<!-- 要将源码放上去需要加入这个插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1</version>
<configuration>
@@ -132,21 +122,8 @@
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.4</version>
<version>2.7</version>
</plugin>
</plugins>
</reporting>
<!-- distribute目录 -->
<distributionManagement>
<repository>
<id>repo</id>
<name>User Project Releases</name>
<url>http://192.168.1.204:8081/nexus/content/repositories/releases</url>
</repository>
<snapshotRepository>
<id>repo</id>
<name>User Project SNAPSHOTS</name>
<url>http://192.168.1.204:8081/nexus/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
</project>

View File

@@ -12,18 +12,6 @@
//
package org.artofsolving.jodconverter;
import static org.artofsolving.jodconverter.office.OfficeUtils.SERVICE_DESKTOP;
import static org.artofsolving.jodconverter.office.OfficeUtils.cast;
import static org.artofsolving.jodconverter.office.OfficeUtils.toUnoProperties;
import static org.artofsolving.jodconverter.office.OfficeUtils.toUrl;
import java.io.File;
import java.util.Map;
import org.artofsolving.jodconverter.office.OfficeContext;
import org.artofsolving.jodconverter.office.OfficeException;
import org.artofsolving.jodconverter.office.OfficeTask;
import com.sun.star.frame.XComponentLoader;
import com.sun.star.frame.XStorable;
import com.sun.star.io.IOException;
@@ -32,6 +20,14 @@ import com.sun.star.lang.XComponent;
import com.sun.star.task.ErrorCodeIOException;
import com.sun.star.util.CloseVetoException;
import com.sun.star.util.XCloseable;
import org.artofsolving.jodconverter.office.OfficeContext;
import org.artofsolving.jodconverter.office.OfficeException;
import org.artofsolving.jodconverter.office.OfficeTask;
import java.io.File;
import java.util.Map;
import static org.artofsolving.jodconverter.office.OfficeUtils.*;
public abstract class AbstractConversionTask implements OfficeTask {
@@ -47,6 +43,7 @@ public abstract class AbstractConversionTask implements OfficeTask {
protected abstract Map<String,?> getStoreProperties(File outputFile, XComponent document);
@Override
public void execute(OfficeContext context) throws OfficeException {
XComponent document = null;
try {
@@ -79,6 +76,7 @@ public abstract class AbstractConversionTask implements OfficeTask {
}
XComponentLoader loader = cast(XComponentLoader.class, context.getService(SERVICE_DESKTOP));
Map<String,?> loadProperties = getLoadProperties(inputFile);
XComponent document = null;
try {
document = loader.loadComponentFromURL(toUrl(inputFile), "_blank", 0, toUnoProperties(loadProperties));

View File

@@ -12,18 +12,18 @@
//
package org.artofsolving.jodconverter;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import com.sun.star.document.UpdateDocMode;
import org.apache.commons.io.FilenameUtils;
import org.artofsolving.jodconverter.document.DefaultDocumentFormatRegistry;
import org.artofsolving.jodconverter.document.DocumentFormat;
import org.artofsolving.jodconverter.document.DocumentFormatRegistry;
import org.artofsolving.jodconverter.model.FileProperties;
import org.artofsolving.jodconverter.office.OfficeException;
import org.artofsolving.jodconverter.office.OfficeManager;
import com.sun.star.document.UpdateDocMode;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
public class OfficeDocumentConverter {
@@ -60,14 +60,22 @@ public class OfficeDocumentConverter {
public void convert(File inputFile, File outputFile) throws OfficeException {
String outputExtension = FilenameUtils.getExtension(outputFile.getName());
DocumentFormat outputFormat = formatRegistry.getFormatByExtension(outputExtension);
convert(inputFile, outputFile, outputFormat);
convert(inputFile, outputFile, outputFormat, null);
}
public void convert(File inputFile, File outputFile, DocumentFormat outputFormat) throws OfficeException {
public void convert(File inputFile, File outputFile, FileProperties fileProperties) throws OfficeException {
String outputExtension = FilenameUtils.getExtension(outputFile.getName());
DocumentFormat outputFormat = formatRegistry.getFormatByExtension(outputExtension);
convert(inputFile, outputFile, outputFormat, fileProperties);
}
public void convert(File inputFile, File outputFile, DocumentFormat outputFormat, FileProperties fileProperties) throws OfficeException {
String inputExtension = FilenameUtils.getExtension(inputFile.getName());
DocumentFormat inputFormat = formatRegistry.getFormatByExtension(inputExtension);
Map<String, Object> properties = fileProperties.toMap();
properties.putAll(defaultLoadProperties);
StandardConversionTask conversionTask = new StandardConversionTask(inputFile, outputFile, outputFormat);
conversionTask.setDefaultLoadProperties(defaultLoadProperties);
conversionTask.setDefaultLoadProperties(properties);
conversionTask.setInputFormat(inputFormat);
officeManager.execute(conversionTask);
}

View File

@@ -14,6 +14,7 @@ package org.artofsolving.jodconverter.cli;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
@@ -86,7 +87,7 @@ public class Convert {
DocumentFormatRegistry registry;
if (commandLine.hasOption(OPTION_REGISTRY.getOpt())) {
File registryFile = new File(commandLine.getOptionValue(OPTION_REGISTRY.getOpt()));
registry = new JsonDocumentFormatRegistry(FileUtils.readFileToString(registryFile));
registry = new JsonDocumentFormatRegistry(FileUtils.readFileToString(registryFile, Charset.defaultCharset()));
} else {
registry = new DefaultDocumentFormatRegistry();
}

View File

@@ -14,6 +14,7 @@ package org.artofsolving.jodconverter.document;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
@@ -25,7 +26,7 @@ import org.json.JSONObject;
public class JsonDocumentFormatRegistry extends SimpleDocumentFormatRegistry {
public JsonDocumentFormatRegistry(InputStream input) throws JSONException, IOException {
readJsonArray(IOUtils.toString(input));
readJsonArray(IOUtils.toString(input, Charset.defaultCharset()));
}
public JsonDocumentFormatRegistry(String source) throws JSONException {

View File

@@ -0,0 +1,34 @@
package org.artofsolving.jodconverter.model;
import java.util.HashMap;
import java.util.Map;
/**
* Created by kl on 2018/1/17.
* Content :
*/
public class FileProperties {
private String filePassword;
public FileProperties() {
}
public Map<String, Object> toMap() {
Map<String, Object> map = new HashMap<>();
if (filePassword != null) {
map.put("Password", filePassword);
}
return map;
}
public String getFilePassword() {
return filePassword;
}
public void setFilePassword(String filePassword) {
this.filePassword = filePassword;
}
}

View File

@@ -16,6 +16,7 @@ import static org.artofsolving.jodconverter.process.ProcessManager.PID_NOT_FOUND
import static org.artofsolving.jodconverter.process.ProcessManager.PID_UNKNOWN;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -134,11 +135,11 @@ class OfficeProcess {
logger.fine("no %OFFICE_HOME%/basis-link found; assuming it's OOo 2.x and we don't need to append URE and Basic paths");
return;
}
String basisLinkText = FileUtils.readFileToString(basisLink).trim();
String basisLinkText = FileUtils.readFileToString(basisLink, Charset.defaultCharset()).trim();
File basisHome = new File(officeHome, basisLinkText);
File basisProgram = new File(basisHome, "program");
File ureLink = new File(basisHome, "ure-link");
String ureLinkText = FileUtils.readFileToString(ureLink).trim();
String ureLinkText = FileUtils.readFileToString(ureLink, Charset.defaultCharset()).trim();
File ureHome = new File(basisHome, ureLinkText);
File ureBin = new File(ureHome, "bin");
Map<String,String> environment = processBuilder.environment();

View File

@@ -112,6 +112,8 @@ public class OfficeUtils {
"/opt/libreoffice7.0",
"/opt/libreoffice7.1",
"/opt/libreoffice7.2",
"/opt/libreoffice7.3",
"/opt/libreoffice7.4",
"/opt/openoffice4",
"/usr/lib/openoffice",
"/usr/lib/libreoffice"

View File

@@ -13,6 +13,7 @@
package org.artofsolving.jodconverter.process;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -25,7 +26,6 @@ import org.apache.commons.io.IOUtils;
* <p>
* Should Work on Solaris too, except that the command line string
* returned by <tt>ps</tt> there is limited to 80 characters and this affects
* {@link #findPid(String)}.
*/
public class LinuxProcessManager implements ProcessManager {
@@ -74,9 +74,7 @@ public class LinuxProcessManager implements ProcessManager {
command = args;
}
Process process = new ProcessBuilder(command).start();
@SuppressWarnings("unchecked")
List<String> lines = IOUtils.readLines(process.getInputStream());
return lines;
return IOUtils.readLines(process.getInputStream(), Charset.defaultCharset());
}
}

View File

@@ -20,7 +20,7 @@ public class ConfigUtils {
userDir = userDir.substring(0, userDir.length() - 4);
} else {
String separator = File.separator;
if (userDir.contains(MAIN_DIRECTORY_NAME)) {
if (userDir.endsWith(MAIN_DIRECTORY_NAME)) {
userDir = userDir + separator + "src" + separator + "main";
} else {
userDir = userDir + separator + MAIN_DIRECTORY_NAME + separator + "src" + separator + "main";

31
pom.xml
View File

@@ -6,13 +6,42 @@
<groupId>cn.keking</groupId>
<artifactId>kkFileView-parent</artifactId>
<version>4.1.0-SNAPSHOT</version>
<version>4.1.0</version>
<properties>
<java.version>1.8</java.version>
<spring.boot.version>2.4.2</spring.boot.version>
<poi.version>5.2.2</poi.version>
<xdocreport.version>1.0.6</xdocreport.version>
<xstream.version>1.4.19</xstream.version>
<junrar.version>7.4.1</junrar.version>
<redisson.version>3.2.0</redisson.version>
<sevenzipjbinding.version>16.02-2.01</sevenzipjbinding.version>
<tukaani.version>1.8</tukaani.version>
<jchardet.version>1.0</jchardet.version>
<antlr.version>2.7.7</antlr.version>
<concurrentlinkedhashmap.version>1.4.2</concurrentlinkedhashmap.version>
<rocksdb.version>5.17.2</rocksdb.version>
<pdfbox.version>2.0.26</pdfbox.version>
<jai-imageio.version>1.4.0</jai-imageio.version>
<jbig2-imageio.version>3.0.4</jbig2-imageio.version>
<galimatias.version>0.2.1</galimatias.version>
<bytedeco.version>1.5.2</bytedeco.version>
<opencv.version>4.1.2-1.5.2</opencv.version>
<openblas.version>0.3.6-1.5.1</openblas.version>
<ffmpeg.version>4.2.1-1.5.2</ffmpeg.version>
<itext.version>2.1.7</itext.version>
<httpclient.version>3.1</httpclient.version>
<commons-cli.version>1.2</commons-cli.version>
<commons-net.version>3.6</commons-net.version>
<commons-lang3.version>3.7</commons-lang3.version>
<commons-compress.version>1.21</commons-compress.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>

View File

@@ -6,7 +6,7 @@
<parent>
<artifactId>kkFileView-parent</artifactId>
<groupId>cn.keking</groupId>
<version>4.1.0-SNAPSHOT</version>
<version>4.1.0</version>
</parent>
<artifactId>kkFileView</artifactId>
@@ -25,20 +25,12 @@
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!-- rar5 的支持 和其他众多压缩支持 可参考 package net.sf.sevenzipjbinding.ArchiveFormat; -->
<dependency>
<groupId>net.sf.sevenzipjbinding</groupId>
<artifactId>sevenzipjbinding</artifactId>
<version>16.02-2.01</version>
</dependency>
<dependency>
<groupId>net.sf.sevenzipjbinding</groupId>
<artifactId>sevenzipjbinding-all-platforms</artifactId>
<version>16.02-2.01</version>
<groupId>cn.keking</groupId>
<artifactId>office-plugin</artifactId>
<version>${project.version}</version>
</dependency>
<!-- web start -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
@@ -53,42 +45,32 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>cn.keking</groupId>
<artifactId>office-plugin</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>
<!-- REDISSON -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.2.0</version>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!-- web end -->
<!-- poi start -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>3.12</version>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>org.apache.poi.xwpf.converter.core</artifactId>
<version>1.0.5</version>
<version>${xdocreport.version}</version>
<exclusions>
<exclusion>
<artifactId>poi</artifactId>
@@ -99,45 +81,220 @@
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>org.apache.poi.xwpf.converter.xhtml</artifactId>
<version>1.0.5</version>
<version>${xdocreport.version}</version>
</dependency>
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.xdocreport.document</artifactId>
<version>1.0.5</version>
<version>${xdocreport.version}</version>
</dependency>
<!-- poi start -->
<!-- rar5 的支持 和其他众多压缩支持 可参考 package net.sf.sevenzipjbinding.ArchiveFormat; -->
<dependency>
<groupId>net.sf.sevenzipjbinding</groupId>
<artifactId>sevenzipjbinding</artifactId>
<version>${sevenzipjbinding.version}</version>
</dependency>
<dependency>
<groupId>net.sf.sevenzipjbinding</groupId>
<artifactId>sevenzipjbinding-all-platforms</artifactId>
<version>${sevenzipjbinding.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>${redisson.version}</version>
</dependency>
<!-- 解压(apache) -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.21</version>
<version>${commons-compress.version}</version>
</dependency>
<!-- 解压(rar)-->
<dependency>
<groupId>com.github.junrar</groupId>
<artifactId>junrar</artifactId>
<version>4.0.0</version>
<version>${junrar.version}</version>
</dependency>
<!-- 解压(7z)-->
<dependency>
<groupId>org.tukaani</groupId>
<artifactId>xz</artifactId>
<version>1.8</version>
<version>${tukaani.version}</version>
</dependency>
<dependency>
<groupId>net.sourceforge.jchardet</groupId>
<artifactId>jchardet</artifactId>
<version>1.0</version>
<version>${jchardet.version}</version>
</dependency>
<dependency>
<groupId>antlr</groupId>
<artifactId>antlr</artifactId>
<version>2.7.7</version>
<version>${antlr.version}</version>
</dependency>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>${commons-cli.version}</version>
</dependency>
<!-- FTP -->
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>${commons-net.version}</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>${xstream.version}</version>
</dependency>
<dependency>
<groupId>com.googlecode.concurrentlinkedhashmap</groupId>
<artifactId>concurrentlinkedhashmap-lru</artifactId>
<version>${concurrentlinkedhashmap.version}</version>
</dependency>
<dependency>
<groupId>org.rocksdb</groupId>
<artifactId>rocksdbjni</artifactId>
<version>${rocksdb.version}</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>${pdfbox.version}</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox-tools</artifactId>
<version>${pdfbox.version}</version>
</dependency>
<dependency>
<groupId>com.github.jai-imageio</groupId>
<artifactId>jai-imageio-jpeg2000</artifactId>
<version>${jai-imageio.version}</version>
</dependency>
<dependency>
<groupId>com.github.jai-imageio</groupId>
<artifactId>jai-imageio-core</artifactId>
<version>${jai-imageio.version}</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>jbig2-imageio</artifactId>
<version>${jbig2-imageio.version}</version>
</dependency>
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-cad</artifactId>
<version>19.9</version>
<scope>system</scope>
<systemPath>${pom.basedir}/lib/aspose-cad-19.9.jar</systemPath>
</dependency>
<!-- 编码识别 -->
<dependency>
<groupId>cpdetector</groupId>
<artifactId>cpdetector</artifactId>
<version>1.04</version>
<scope>system</scope>
<systemPath>${pom.basedir}/lib/cpdetector-1.04.jar</systemPath>
</dependency>
<!-- url 规范化 -->
<dependency>
<groupId>io.mola.galimatias</groupId>
<artifactId>galimatias</artifactId>
<version>${galimatias.version}</version>
</dependency>
<!-- 以下是bytedeco 基于opencv ffmpeg封装的javacv用于视频处理 -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>${bytedeco.version}</version>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId>
<version>${bytedeco.version}</version>
</dependency>
<!-- 此版本中主要兼容linux和windows系统如需兼容其他系统平台请引入对应依赖即可 -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv</artifactId>
<version>${opencv.version}</version>
<classifier>linux-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv</artifactId>
<version>${opencv.version}</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
<version>${openblas.version}</version>
<classifier>linux-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
<version>${openblas.version}</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg</artifactId>
<version>${ffmpeg.version}</version>
<classifier>linux-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg</artifactId>
<version>${ffmpeg.version}</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>com.lowagie</groupId>
<artifactId>itext</artifactId>
<version>${itext.version}</version>
</dependency>
<dependency>
<groupId>javax.media</groupId>
<artifactId>jai_core</artifactId>
<version>1.1.3</version>
<scope>system</scope>
<systemPath>${pom.basedir}/lib/jai_core-1.1.3.jar</systemPath>
</dependency>
<dependency>
<groupId>javax.media</groupId>
<artifactId>jai_codec</artifactId>
<version>1.1.3</version>
<scope>system</scope>
<systemPath>${pom.basedir}/lib/jai_codec-1.1.3.jar</systemPath>
</dependency>
<!-- test dependency - start -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
<version>${httpclient.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
@@ -146,143 +303,7 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.2</version>
</dependency>
<!-- FTP -->
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.6</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.18</version>
</dependency>
<dependency>
<groupId>com.googlecode.concurrentlinkedhashmap</groupId>
<artifactId>concurrentlinkedhashmap-lru</artifactId>
<version>1.4.2</version>
</dependency>
<dependency>
<groupId>org.rocksdb</groupId>
<artifactId>rocksdbjni</artifactId>
<version>5.17.2</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.24</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox-tools</artifactId>
<version>2.0.15</version>
</dependency>
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-cad</artifactId>
<version>19.9</version>
<scope>system</scope>
<systemPath>${basedir}/lib/aspose-cad-19.9.jar</systemPath>
</dependency>
<!-- 编码识别 -->
<dependency>
<groupId>cpdetector</groupId>
<artifactId>cpdetector</artifactId>
<version>1.04</version>
<scope>system</scope>
<systemPath>${basedir}/lib/cpdetector-1.04.jar</systemPath>
</dependency>
<!-- url 规范化 -->
<dependency>
<groupId>io.mola.galimatias</groupId>
<artifactId>galimatias</artifactId>
<version>0.2.1</version>
</dependency>
<!-- 以下是bytedeco 基于opencv ffmpeg封装的javacv用于视频处理 -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.5.2</version>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId>
<version>1.5.2</version>
</dependency>
<!-- 此版本中主要兼容linux和windows系统如需兼容其他系统平台请引入对应依赖即可 -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv</artifactId>
<version>4.1.2-1.5.2</version>
<classifier>linux-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv</artifactId>
<version>4.1.2-1.5.2</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
<version>0.3.6-1.5.1</version>
<classifier>linux-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
<version>0.3.6-1.5.1</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg</artifactId>
<version>4.2.1-1.5.2</version>
<classifier>linux-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg</artifactId>
<version>4.2.1-1.5.2</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>com.lowagie</groupId>
<artifactId>itext</artifactId>
<version>2.1.7</version>
</dependency>
<dependency>
<groupId>javax.media</groupId>
<artifactId>jai_core</artifactId>
<version>1.1.3</version>
<scope>system</scope>
<systemPath>${basedir}/lib/jai_core-1.1.3.jar</systemPath>
</dependency>
<dependency>
<groupId>javax.media</groupId>
<artifactId>jai_codec</artifactId>
<version>1.1.3</version>
<scope>system</scope>
<systemPath>${basedir}/lib/jai_codec-1.1.3.jar</systemPath>
</dependency>
<!-- test dependency - end -->
</dependencies>
<build>
@@ -316,7 +337,9 @@
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.4.2</version>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
@@ -336,5 +359,4 @@
</plugin>
</plugins>
</build>
</project>

View File

@@ -2,12 +2,12 @@
cd /tmp
install_redhat() {
wget https://kkfileview.keking.cn/LibreOffice_7.1.4_Linux_x86-64_rpm.tar.gz -cO LibreOffice_7_rpm.tar.gz && tar -zxf /tmp/LibreOffice_7_rpm.tar.gz && cd /tmp/LibreOffice_7.1.4.2_Linux_x86-64_rpm/RPMS
wget https://kkfileview.keking.cn/LibreOffice_7.3.7_Linux_x86-64_rpm.tar.gz -cO LibreOffice_7_rpm.tar.gz && tar -zxf /tmp/LibreOffice_7_rpm.tar.gz && cd /tmp/LibreOffice_7.3.7.2_Linux_x86-64_rpm/RPMS
echo $?
if [ $? -eq 0 ];then
yum install -y libXext.x86_64
yum install -y libSM.x86_64 libXrender.x86_64 libXext.x86_64
yum groupinstall -y "X Window System"
yum localinstall *.rpm
yum localinstall -y *.rpm
echo 'install finshed...'
else
echo 'download package error...'
@@ -15,7 +15,7 @@ install_redhat() {
}
install_ubuntu() {
wget https://kkfileview.keking.cn/LibreOffice_7.1.4_Linux_x86-64_deb.tar.gz -cO LibreOffice_7_deb.tar.gz && tar -zxf /tmp/LibreOffice_7_deb.tar.gz && cd /tmp/LibreOffice_7.1.4.2_Linux_x86-64_deb/DEBS
wget https://kkfileview.keking.cn/LibreOffice_7.3.7_Linux_x86-64_deb.tar.gz -cO LibreOffice_7_deb.tar.gz && tar -zxf /tmp/LibreOffice_7_deb.tar.gz && cd /tmp/LibreOffice_7.3.7.2_Linux_x86-64_deb/DEBS
echo $?
if [ $? -eq 0 ];then
apt-get install -y libxinerama1 libcairo2 libcups2 libx11-xcb1

View File

@@ -5,5 +5,6 @@ echo Using KKFILEVIEW_BIN_FOLDER %KKFILEVIEW_BIN_FOLDER%
echo Starting kkFileView...
echo Please check log file in ../log/kkFileView.log for more information
echo You can get help in our official home site: https://kkFileView.keking.cn
echo If you need further help, please join our kk opensource community: https://t.zsxq.com/09ZHSXbsQ
echo If this project is helpful to you, please star it on https://gitee.com/kekingcn/file-online-preview/stargazers
java -Dspring.config.location=..\config\application.properties -jar kkFileView-4.1.0-SNAPSHOT.jar -> ..\log\kkFileView.log
java -Dspring.config.location=..\config\application.properties -jar kkFileView-4.1.0.jar -> ..\log\kkFileView.log

View File

@@ -9,7 +9,7 @@
# Description: v1.1修改进程启动机制为pid形式
#############################
#
DIR_HOME=("/opt/openoffice.org3" "/opt/libreoffice" "/opt/libreoffice6.1" "/opt/libreoffice7.0" "/opt/libreoffice7.1" "/opt/openoffice4" "/usr/lib/openoffice" "/usr/lib/libreoffice")
DIR_HOME=("/opt/openoffice.org3" "/opt/libreoffice" "/opt/libreoffice6.1" "/opt/libreoffice7.0" "/opt/libreoffice7.1" "/opt/libreoffice7.2" "/opt/libreoffice7.3" "/opt/libreoffice7.4" "/opt/openoffice4" "/usr/lib/openoffice" "/usr/lib/libreoffice")
FLAG=
OFFICE_HOME=
KKFILEVIEW_BIN_FOLDER=$(cd "$(dirname "$0")" || exit 1 ;pwd)
@@ -42,7 +42,7 @@ else
fi
done
if [ ! -n "${FLAG}" ]; then
echo "Installing OpenOffice"
echo "Installing LibreOffice"
sh ./install.sh
else
echo "Detected office component has been installed in $OFFICE_HOME"
@@ -51,9 +51,10 @@ else
## 启动kkFileView
echo "Starting kkFileView..."
nohup java -Dfile.encoding=UTF-8 -Dspring.config.location=../config/application.properties -jar kkFileView-4.1.0-SNAPSHOT.jar > ../log/kkFileView.log 2>&1 &
nohup java -Dfile.encoding=UTF-8 -Dspring.config.location=../config/application.properties -jar kkFileView-4.1.0.jar > ../log/kkFileView.log 2>&1 &
echo "Please execute ./showlog.sh to check log for more information"
echo "You can get help in our official home site: https://kkFileView.keking.cn"
echo "If you need further help, please join our kk opensource community: https://t.zsxq.com/09ZHSXbsQ"
echo "If this project is helpful to you, please star it on https://gitee.com/kekingcn/file-online-preview/stargazers"
PROCESS=$(ps -ef | grep kkFileView | awk 'NR==1{print $2}')
# 启动成功后将进程号写入pid文件

View File

@@ -5,6 +5,8 @@
[#-- @ftlvariable name="file" type="cn.keking.model.FileAttribute" --]
[#-- @ftlvariable name="fileName" type="java.lang.String" --]
[#-- @ftlvariable name="fileTree" type="java.lang.String" --]
[#-- @ftlvariable name="needFilePassword" type="java.lang.Boolean" --]
[#-- @ftlvariable name="filePasswordError" type="java.lang.Boolean" --]
[#-- @ftlvariable name="baseUrl" type="java.lang.String" --]
[#-- @ftlvariable name="imgUrls" type="String" --]
[#-- @ftlvariable name="textData" type="java.lang.String" --]

View File

@@ -1,6 +1,5 @@
package cn.keking;
import cn.keking.config.AppBanner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@@ -23,7 +22,6 @@ public class ServerMain {
stopWatch.start();
ConfigurableApplicationContext context = new SpringApplicationBuilder(ServerMain.class)
.logStartupInfo(false)
.banner(new AppBanner())
.run(args);
stopWatch.stop();
Integer port = context.getBean(ServerProperties.class).getPort();

View File

@@ -1,28 +0,0 @@
package cn.keking.config;
import org.springframework.boot.Banner;
import org.springframework.core.env.Environment;
import java.io.PrintStream;
/**
* @author kl (http://kailing.pub)
* @since 2021/2/8
*/
public class AppBanner implements Banner {
@Override
public void printBanner(Environment environment, Class<?> sourceClass, PrintStream out) {
out.println(
" _ _ ______ _ _ __ __ _ \n" +
" | | | | | ____| (_) | | \\ \\ / / (_) \n" +
" | | __ | | __ | |__ _ | | ___ \\ \\ / / _ ___ __ __\n" +
" | |/ / | |/ / | __| | | | | / _ \\ \\ \\/ / | | / _ \\ \\ \\ /\\ / /\n" +
" | < | < | | | | | | | __/ \\ / | | | __/ \\ V V / \n" +
" |_|\\_\\ |_|\\_\\ |_| |_| |_| \\___| \\/ |_| \\___| \\_/\\_/ \n" +
" \n" +
" => Spring Boot :: (v2.4.2) QQ1 :: 613025121\n" +
" => kkFileView :: (v4.1.0-SNAPSHOT) QQ2 :: 484680571\n" +
" => github :: https://github.com/kekingcn/kkFileView\n" +
" => gitee :: https://gitee.com/kekingcn/file-online-preview\n");
}
}

View File

@@ -6,8 +6,8 @@ import org.springframework.stereotype.Component;
import java.io.File;
import java.util.Arrays;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* @author: chenjh
@@ -275,7 +275,7 @@ public class ConfigConstants {
}
@Value("${pdf.openFile.disable:true}")
public static void setPdfOpenFileDisable(String pdfOpenFileDisable) {
public void setPdfOpenFileDisable(String pdfOpenFileDisable) {
setPdfOpenFileDisableValue(pdfOpenFileDisable);
}
public static void setPdfOpenFileDisableValue(String pdfOpenFileDisable) {
@@ -332,7 +332,7 @@ public class ConfigConstants {
}
@Value("${file.upload.disable:false}")
public static void setFileUploadDisable(Boolean fileUploadDisable) {
public void setFileUploadDisable(Boolean fileUploadDisable) {
setFileUploadDisableValue(fileUploadDisable);
}

View File

@@ -1,11 +1,17 @@
package cn.keking.config;
import cn.keking.web.filter.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.HashSet;
import java.util.Set;
/**
* @author: chenjh
* @since: 2019/4/16 20:04
@@ -23,4 +29,63 @@ public class WebConfig implements WebMvcConfigurer {
LOGGER.info("Add resource locations: {}", filePath);
registry.addResourceHandler("/**").addResourceLocations("classpath:/META-INF/resources/","classpath:/resources/","classpath:/static/","classpath:/public/","file:" + filePath);
}
@Bean
public FilterRegistrationBean<ChinesePathFilter> getChinesePathFilter() {
ChinesePathFilter filter = new ChinesePathFilter();
FilterRegistrationBean<ChinesePathFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(filter);
return registrationBean;
}
@Bean
public FilterRegistrationBean<TrustHostFilter> getTrustHostFilter() {
Set<String> filterUri = new HashSet<>();
filterUri.add("/onlinePreview");
filterUri.add("/picturesPreview");
TrustHostFilter filter = new TrustHostFilter();
FilterRegistrationBean<TrustHostFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(filter);
registrationBean.setUrlPatterns(filterUri);
return registrationBean;
}
@Bean
public FilterRegistrationBean<TrustDirFilter> getTrustDirFilter() {
Set<String> filterUri = new HashSet<>();
filterUri.add("/onlinePreview");
filterUri.add("/picturesPreview");
filterUri.add("/getCorsFile");
TrustDirFilter filter = new TrustDirFilter();
FilterRegistrationBean<TrustDirFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(filter);
registrationBean.setUrlPatterns(filterUri);
return registrationBean;
}
@Bean
public FilterRegistrationBean<BaseUrlFilter> getBaseUrlFilter() {
Set<String> filterUri = new HashSet<>();
filterUri.add("/index");
filterUri.add("/onlinePreview");
filterUri.add("/picturesPreview");
BaseUrlFilter filter = new BaseUrlFilter();
FilterRegistrationBean<BaseUrlFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(filter);
registrationBean.setUrlPatterns(filterUri);
return registrationBean;
}
@Bean
public FilterRegistrationBean<AttributeSetFilter> getWatermarkConfigFilter() {
Set<String> filterUri = new HashSet<>();
filterUri.add("/index");
filterUri.add("/onlinePreview");
filterUri.add("/picturesPreview");
AttributeSetFilter filter = new AttributeSetFilter();
FilterRegistrationBean<AttributeSetFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(filter);
registrationBean.setUrlPatterns(filterUri);
return registrationBean;
}
}

View File

@@ -1,6 +1,7 @@
package cn.keking.model;
import cn.keking.config.ConfigConstants;
import org.artofsolving.jodconverter.model.FileProperties;
/**
* Created by kl on 2018/1/17.
@@ -13,6 +14,8 @@ public class FileAttribute {
private String name;
private String url;
private String fileKey;
private String filePassword;
private String userToken;
private String officePreviewType = ConfigConstants.getOfficePreviewType();
private String tifPreviewType;
private Boolean skipDownLoad = false;
@@ -35,6 +38,12 @@ public class FileAttribute {
this.officePreviewType = officePreviewType;
}
public FileProperties toFileProperties() {
FileProperties fileProperties = new FileProperties();
fileProperties.setFilePassword(filePassword);
return fileProperties;
}
public String getFileKey() {
return fileKey;
}
@@ -43,6 +52,22 @@ public class FileAttribute {
this.fileKey = fileKey;
}
public String getFilePassword() {
return filePassword;
}
public void setFilePassword(String filePassword) {
this.filePassword = filePassword;
}
public String getUserToken() {
return userToken;
}
public void setUserToken(String userToken) {
this.userToken = userToken;
}
public String getOfficePreviewType() {
return officePreviewType;
}
@@ -82,6 +107,7 @@ public class FileAttribute {
public void setUrl(String url) {
this.url = url;
}
public Boolean getSkipDownLoad() {
return skipDownLoad;
}
@@ -89,6 +115,7 @@ public class FileAttribute {
public void setSkipDownLoad(Boolean skipDownLoad) {
this.skipDownLoad = skipDownLoad;
}
public String getTifPreviewType() {
return tifPreviewType;
}
@@ -96,4 +123,5 @@ public class FileAttribute {
public void setTifPreviewType(String previewType) {
this.tifPreviewType = previewType;
}
}

View File

@@ -27,8 +27,8 @@ public enum FileType {
OFD("ofdFilePreviewImpl");
private static final String[] OFFICE_TYPES = {"docx", "wps", "doc", "xls", "xlsx", "ppt", "pptx"};
private static final String[] PICTURE_TYPES = {"jpg", "jpeg", "png", "gif", "bmp", "ico", "raw"};
private static final String[] OFFICE_TYPES = {"docx", "wps", "doc", "docm", "xls", "xlsx", "csv" ,"xlsm", "ppt", "pptx", "vsd", "rtf", "odt", "wmf", "emf", "dps", "et", "ods", "ots", "tsv", "odp", "otp", "sxi", "ott", "vsdx", "fodt", "fods", "xltx","tga","psd"};
private static final String[] PICTURE_TYPES = {"jpg", "jpeg", "png", "gif", "bmp", "ico", "jfif", "webp"};
private static final String[] ARCHIVE_TYPES = {"rar", "zip", "jar", "7-zip", "tar", "gzip", "7z"};
private static final String[] TIFF_TYPES = {"tif", "tiff"};
private static final String[] OFD_TYPES = {"ofd"};

View File

@@ -13,15 +13,12 @@ import com.github.junrar.rarfile.FileHeader;
import net.sf.sevenzipjbinding.*;
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
import net.sf.sevenzipjbinding.simple.ISimpleInArchive;
import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
import org.apache.commons.compress.archivers.sevenz.SevenZFile;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.apache.commons.io.FileUtils;
import org.springframework.stereotype.Component;
import java.io.*;
import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.text.CollationKey;
import java.text.Collator;
import java.util.*;
@@ -47,57 +44,92 @@ public class CompressFileReader {
this.fileHandlerService = fileHandlerService;
}
public String readZipFile(String filePath, String fileKey) {
String archiveSeparator = "/";
Map<String, FileNode> appender = new HashMap<>();
List<String> imgUrls = new LinkedList<>();
String baseUrl = BaseUrlFilter.getBaseUrl();
String archiveFileName = fileHandlerService.getFileNameFromPath(filePath);
try {
ZipFile zipFile = new ZipFile(filePath, KkFileUtils.getFileEncode(filePath));
Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
// 排序
entries = sortZipEntries(entries);
List<Map<String, ZipArchiveEntry>> entriesToBeExtracted = new LinkedList<>();
while (entries.hasMoreElements()) {
ZipArchiveEntry entry = entries.nextElement();
String fullName = entry.getName().replaceAll("//", "").replaceAll("\\\\", "");
int level = fullName.split(archiveSeparator).length;
// 展示名
String originName = getLastFileName(fullName, archiveSeparator);
String childName = level + "_" + originName;
boolean directory = entry.isDirectory();
if (!directory) {
childName = archiveFileName + "_" + originName;
entriesToBeExtracted.add(Collections.singletonMap(childName, entry));
public static byte[] getUTF8BytesFromGBKString(String gbkStr) {
int n = gbkStr.length();
byte[] utfBytes = new byte[3 * n];
int k = 0;
for (int i = 0; i < n; i++) {
int m = gbkStr.charAt(i);
if (m < 128 && m >= 0) {
utfBytes[k++] = (byte) m;
continue;
}
String parentName = getLast2FileName(fullName, archiveSeparator, archiveFileName);
parentName = (level - 1) + "_" + parentName;
FileType type = FileType.typeFromUrl(childName);
if (type.equals(FileType.PICTURE)) {//添加图片文件到图片列表
imgUrls.add(baseUrl + childName);
utfBytes[k++] = (byte) (0xe0 | (m >> 12));
utfBytes[k++] = (byte) (0x80 | ((m >> 6) & 0x3f));
utfBytes[k++] = (byte) (0x80 | (m & 0x3f));
}
FileNode node = new FileNode(originName, childName, parentName, new ArrayList<>(), directory, fileKey);
addNodes(appender, parentName, node);
appender.put(childName, node);
}
// 开启新的线程处理文件解压
executors.submit(new ZipExtractorWorker(entriesToBeExtracted, zipFile, filePath));
fileHandlerService.putImgCache(fileKey, imgUrls);
return new ObjectMapper().writeValueAsString(appender.get(""));
} catch (IOException e) {
e.printStackTrace();
return null;
if (k < utfBytes.length) {
byte[] tmp = new byte[k];
System.arraycopy(utfBytes, 0, tmp, 0, k);
return tmp;
}
return utfBytes;
}
private Enumeration<ZipArchiveEntry> sortZipEntries(Enumeration<ZipArchiveEntry> entries) {
List<ZipArchiveEntry> sortedEntries = new LinkedList<>();
while (entries.hasMoreElements()) {
sortedEntries.add(entries.nextElement());
public String getUtf8String(String str) {
if (str != null && str.length() > 0) {
String needEncodeCode = "ISO-8859-1";
String neeEncodeCode = "ISO-8859-2";
String gbkEncodeCode = "GBK";
try {
if (Charset.forName(needEncodeCode).newEncoder().canEncode(str)) {
str = new String(str.getBytes(needEncodeCode), StandardCharsets.UTF_8);
}
sortedEntries.sort(Comparator.comparingInt(o -> o.getName().length()));
return Collections.enumeration(sortedEntries);
if (Charset.forName(neeEncodeCode).newEncoder().canEncode(str)) {
str = new String(str.getBytes(neeEncodeCode), StandardCharsets.UTF_8);
}
if (Charset.forName(gbkEncodeCode).newEncoder().canEncode(str)) {
str = new String(getUTF8BytesFromGBKString(str), StandardCharsets.UTF_8);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
return str;
}
/**
* 判断是否是中日韩文字
*/
private static boolean isChinese(char c) {
Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
|| ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
|| ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
|| ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
|| ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
|| ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {
return true;
}
return false;
}
public static boolean judge(char c){
if((c >='0' && c<='9')||(c >='a' && c<='z' || c >='A' && c<='Z')){
return true;
}
return false;
}
public static boolean isMessyCode(String strName) {
//去除字符串中的空格 制表符 换行 回车
Pattern p = Pattern.compile("\\s*|\t*|\r*|\n*");
Matcher m = p.matcher(strName);
String after = m.replaceAll("");
//去除字符串中的标点符号
String temp = after.replaceAll("\\p{P}", "");
//处理之后转换成字符数组
char[] ch = temp.trim().toCharArray();
for (int i = 0; i < ch.length; i++) {
char c = ch[i];
//判断是否是数字或者英文字符
if (!judge(c)) {
//判断是否是中日韩文
if (!isChinese(c)) {
//如果不是数字或者英文字符也不是中日韩文则表示是乱码返回true
return true;
}
}
}
//表示不是乱码 返回false
return false;
}
public String unRar(String filePath, String fileKey) {
@@ -110,14 +142,14 @@ public class CompressFileReader {
List<Map<String, FileHeaderRar>> headersToBeExtract = new ArrayList<>();
for (FileHeaderRar header : items) {
String fullName = header.getFileNameW();
String originName = getLastFileName(fullName, File.separator);
String originName = getLastFileName(fullName);
String childName = originName;
boolean directory = header.getDirectory();
if (!directory) {
childName = archiveFileName + "_" + originName;
headersToBeExtract.add(Collections.singletonMap(childName, header));
}
String parentName = getLast2FileName(fullName, File.separator, archiveFileName);
String parentName = getLast2FileName(fullName, archiveFileName);
FileType type = FileType.typeFromUrl(childName);
if (type.equals(FileType.PICTURE)) {
imgUrls.add(baseUrl + childName);
@@ -147,14 +179,17 @@ public class CompressFileReader {
String extractPath = paths.substring(0, paths.lastIndexOf(folderName));
inArchive.extract(null, false, new ExtractCallback(inArchive, extractPath, folderName + "_"));
ISimpleInArchive simpleInArchive = inArchive.getSimpleInterface();
itemPath =
Arrays.stream(simpleInArchive.getArchiveItems())
.map(
o -> {
itemPath = Arrays.stream(simpleInArchive.getArchiveItems()).map(o -> {
try {
return new FileHeaderRar(o.getPath(), o.isFolder());
String path = getUtf8String(o.getPath());
if (isMessyCode(path)){
path = new String(o.getPath().getBytes(StandardCharsets.ISO_8859_1), "GBK");
}
return new FileHeaderRar(path, o.isFolder());
} catch (SevenZipException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
})
@@ -183,59 +218,6 @@ public class CompressFileReader {
return itemPath;
}
public String read7zFile(String filePath, String fileKey) {
String archiveSeparator = "/";
Map<String, FileNode> appender = new HashMap<>();
List<String> imgUrls = new ArrayList<>();
String baseUrl = BaseUrlFilter.getBaseUrl();
String archiveFileName = fileHandlerService.getFileNameFromPath(filePath);
try {
SevenZFile zipFile = new SevenZFile(new File(filePath));
Iterable<SevenZArchiveEntry> entries = zipFile.getEntries();
// 排序
Enumeration<SevenZArchiveEntry> newEntries = sortSevenZEntries(entries);
List<Map<String, SevenZArchiveEntry>> entriesToBeExtracted = new ArrayList<>();
while (newEntries.hasMoreElements()) {
SevenZArchiveEntry entry = newEntries.nextElement();
String fullName = entry.getName().replaceAll("//", "").replaceAll("\\\\", "");
int level = fullName.split(archiveSeparator).length;
// 展示名
String originName = getLastFileName(fullName, archiveSeparator);
String childName = level + "_" + originName;
boolean directory = entry.isDirectory();
if (!directory) {
childName = archiveFileName + "_" + originName;
entriesToBeExtracted.add(Collections.singletonMap(childName, entry));
}
String parentName = getLast2FileName(fullName, archiveSeparator, archiveFileName);
parentName = (level - 1) + "_" + parentName;
FileType type = FileType.typeFromUrl(childName);
if (type.equals(FileType.PICTURE)) {//添加图片文件到图片列表
imgUrls.add(baseUrl + childName);
}
FileNode node = new FileNode(originName, childName, parentName, new ArrayList<>(), directory, fileKey);
addNodes(appender, parentName, node);
appender.put(childName, node);
}
// 开启新的线程处理文件解压
executors.submit(new SevenZExtractorWorker(entriesToBeExtracted, filePath));
fileHandlerService.putImgCache(fileKey, imgUrls);
return new ObjectMapper().writeValueAsString(appender.get(""));
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
private Enumeration<SevenZArchiveEntry> sortSevenZEntries(Iterable<SevenZArchiveEntry> entries) {
List<SevenZArchiveEntry> sortedEntries = new ArrayList<>();
for (SevenZArchiveEntry entry : entries) {
sortedEntries.add(entry);
}
return Collections.enumeration(sortedEntries);
}
private void addNodes(Map<String, FileNode> appender, String parentName, FileNode node) {
if (appender.containsKey(parentName)) {
appender.get(parentName).getChildList().add(node);
@@ -249,53 +231,28 @@ public class CompressFileReader {
}
}
private List<FileHeader> sortedHeaders(List<FileHeader> headers) {
List<FileHeader> sortedHeaders = new ArrayList<>();
Map<Integer, FileHeader> mapHeaders = new TreeMap<>();
headers.forEach(
header ->
mapHeaders.put(
new Integer(0).equals(header.getFileNameW().length())
? header.getFileNameString().length()
: header.getFileNameW().length(),
header));
for (Map.Entry<Integer, FileHeader> entry : mapHeaders.entrySet()) {
for (FileHeader header : headers) {
if (entry
.getKey()
.equals(
new Integer(0).equals(header.getFileNameW().length())
? header.getFileNameString().length()
: header.getFileNameW().length())) {
sortedHeaders.add(header);
}
}
}
return sortedHeaders;
}
private static String getLast2FileName(String fullName, String seperator, String rootName) {
if (fullName.endsWith(seperator)) {
private static String getLast2FileName(String fullName, String rootName) {
if (fullName.endsWith(File.separator)) {
fullName = fullName.substring(0, fullName.length() - 1);
}
// 1.获取剩余部分
int endIndex = fullName.lastIndexOf(seperator);
int endIndex = fullName.lastIndexOf(File.separator);
String leftPath = fullName.substring(0, endIndex == -1 ? 0 : endIndex);
if (leftPath.length() > 1) {
// 2.获取倒数第二个
return getLastFileName(leftPath, seperator);
return getLastFileName(leftPath);
} else {
return rootName;
}
}
private static String getLastFileName(String fullName, String seperator) {
if (fullName.endsWith(seperator)) {
private static String getLastFileName(String fullName) {
if (fullName.endsWith(File.separator)) {
fullName = fullName.substring(0, fullName.length() - 1);
}
String newName = fullName;
if (fullName.contains(seperator)) {
newName = fullName.substring(fullName.lastIndexOf(seperator) + 1);
if (fullName.contains(File.separator)) {
newName = fullName.substring(fullName.lastIndexOf(File.separator) + 1);
}
return newName;
}
@@ -411,95 +368,6 @@ public class CompressFileReader {
}
}
class ZipExtractorWorker implements Runnable {
private final List<Map<String, ZipArchiveEntry>> entriesToBeExtracted;
private final ZipFile zipFile;
private final String filePath;
public ZipExtractorWorker(List<Map<String, ZipArchiveEntry>> entriesToBeExtracted, ZipFile zipFile, String filePath) {
this.entriesToBeExtracted = entriesToBeExtracted;
this.zipFile = zipFile;
this.filePath = filePath;
}
@Override
public void run() {
for (Map<String, ZipArchiveEntry> entryMap : entriesToBeExtracted) {
String childName = entryMap.keySet().iterator().next();
ZipArchiveEntry entry = entryMap.values().iterator().next();
try {
extractZipFile(childName, zipFile.getInputStream(entry));
} catch (IOException e) {
e.printStackTrace();
}
}
try {
zipFile.close();
} catch (IOException e) {
e.printStackTrace();
}
KkFileUtils.deleteFileByPath(filePath);
}
private void extractZipFile(String childName, InputStream zipFile) {
String outPath = fileDir + childName;
try (OutputStream ot = new FileOutputStream(outPath)) {
byte[] inByte = new byte[1024];
int len;
while ((-1 != (len = zipFile.read(inByte)))) {
ot.write(inByte, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class SevenZExtractorWorker implements Runnable {
private final List<Map<String, SevenZArchiveEntry>> entriesToBeExtracted;
private final String filePath;
public SevenZExtractorWorker(List<Map<String, SevenZArchiveEntry>> entriesToBeExtracted, String filePath) {
this.entriesToBeExtracted = entriesToBeExtracted;
this.filePath = filePath;
}
@Override
public void run() {
try {
SevenZFile sevenZFile = new SevenZFile(new File(filePath));
SevenZArchiveEntry entry = sevenZFile.getNextEntry();
while (entry != null) {
if (entry.isDirectory()) {
entry = sevenZFile.getNextEntry();
continue;
}
String childName = "default_file";
SevenZArchiveEntry entry1;
for (Map<String, SevenZArchiveEntry> entryMap : entriesToBeExtracted) {
childName = entryMap.keySet().iterator().next();
entry1 = entryMap.values().iterator().next();
if (entry.getName().equals(entry1.getName())) {
break;
}
}
FileOutputStream out = new FileOutputStream(fileDir + childName);
byte[] content = new byte[(int) entry.getSize()];
sevenZFile.read(content, 0, content.length);
out.write(content);
out.close();
entry = sevenZFile.getNextEntry();
}
sevenZFile.close();
} catch (IOException e) {
e.printStackTrace();
}
KkFileUtils.deleteFileByPath(filePath);
}
}
class RarExtractorWorker implements Runnable {
private final List<Map<String, FileHeader>> headersToBeExtracted;
@@ -618,6 +486,5 @@ public class CompressFileReader {
@Override
public void setOperationResult(ExtractOperationResult extractOperationResult) {
}
}
}

View File

@@ -149,7 +149,7 @@ public class FileHandlerService {
sb.append(line);
}
// 添加sheet控制头
sb.append("<script src=\"js/jquery-3.0.0.min.js\" type=\"text/javascript\"></script>");
sb.append("<script src=\"js/jquery-3.6.1.min.js\" type=\"text/javascript\"></script>");
sb.append("<script src=\"js/excel.header.js\" type=\"text/javascript\"></script>");
sb.append("<link rel=\"stylesheet\" href=\"bootstrap/css/bootstrap.min.css\">");
} catch (IOException e) {
@@ -292,7 +292,18 @@ public class FileHandlerService {
if (StringUtils.hasText(tifPreviewType)) {
attribute.setTifPreviewType(tifPreviewType);
}
String filePassword = req.getParameter("filePassword");
if (StringUtils.hasText(filePassword)) {
attribute.setFilePassword(filePassword);
}
String userToken = req.getParameter("userToken");
if (StringUtils.hasText(userToken)) {
attribute.setUserToken(userToken);
}
}
return attribute;
}

View File

@@ -6,6 +6,7 @@ import org.artofsolving.jodconverter.OfficeDocumentConverter;
import org.artofsolving.jodconverter.office.DefaultOfficeManagerConfiguration;
import org.artofsolving.jodconverter.office.OfficeManager;
import org.artofsolving.jodconverter.office.OfficeUtils;
import org.artofsolving.jodconverter.util.PlatformUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
@@ -24,7 +25,6 @@ import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/**
* 创建文件转换器
@@ -97,9 +97,8 @@ public class OfficePluginManager {
private boolean killProcess() {
boolean flag = false;
Properties props = System.getProperties();
try {
if (props.getProperty("os.name").toLowerCase().contains("windows")) {
if (PlatformUtils.isWindows()) {
Process p = Runtime.getRuntime().exec("cmd /c tasklist ");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream os = p.getInputStream();
@@ -112,6 +111,20 @@ public class OfficePluginManager {
Runtime.getRuntime().exec("taskkill /im " + "soffice.bin" + " /f");
flag = true;
}
} else if (PlatformUtils.isLinux()) {
Process p = Runtime.getRuntime().exec(new String[]{"sh", "-c", "ps -ef | grep " + "soffice.bin" + " |grep -v grep | wc -l"});
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream os = p.getInputStream();
byte[] b = new byte[256];
while (os.read(b) > 0) {
baos.write(b);
}
String s = baos.toString();
if (!s.startsWith("0")) {
String[] cmd = {"sh", "-c", "ps -ef | grep soffice.bin | grep -v grep | awk '{print \"kill -9 \"$2}' | sh"};
Runtime.getRuntime().exec(cmd);
flag = true;
}
} else {
Process p = Runtime.getRuntime().exec(new String[]{"sh", "-c", "ps -ef | grep " + "soffice.bin"});
ByteArrayOutputStream baos = new ByteArrayOutputStream();

View File

@@ -1,5 +1,6 @@
package cn.keking.service;
import cn.keking.model.FileAttribute;
import org.artofsolving.jodconverter.OfficeDocumentConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -20,22 +21,23 @@ public class OfficeToPdfService {
this.officePluginManager = officePluginManager;
}
public void openOfficeToPDF(String inputFilePath, String outputFilePath) {
office2pdf(inputFilePath, outputFilePath);
public void openOfficeToPDF(String inputFilePath, String outputFilePath, FileAttribute fileAttribute) {
office2pdf(inputFilePath, outputFilePath, fileAttribute);
}
public static void converterFile(File inputFile, String outputFilePath_end, OfficeDocumentConverter converter) {
public static void converterFile(File inputFile, String outputFilePath_end, OfficeDocumentConverter converter, FileAttribute fileAttribute) {
File outputFile = new File(outputFilePath_end);
// 假如目标路径不存在,则新建该路径
if (!outputFile.getParentFile().exists() && !outputFile.getParentFile().mkdirs()) {
logger.error("创建目录【{}】失败,请检查目录权限!",outputFilePath_end);
}
converter.convert(inputFile, outputFile);
converter.convert(inputFile, outputFile, fileAttribute.toFileProperties());
}
public void office2pdf(String inputFilePath, String outputFilePath) {
public void office2pdf(String inputFilePath, String outputFilePath, FileAttribute fileAttribute) {
OfficeDocumentConverter converter = officePluginManager.getDocumentConverter();
if (null != inputFilePath) {
File inputFile = new File(inputFilePath);
@@ -45,12 +47,12 @@ public class OfficeToPdfService {
String outputFilePath_end = getOutputFilePath(inputFilePath);
if (inputFile.exists()) {
// 找不到源文件, 则返回
converterFile(inputFile, outputFilePath_end,converter);
converterFile(inputFile, outputFilePath_end, converter, fileAttribute);
}
} else {
if (inputFile.exists()) {
// 找不到源文件, 则返回
converterFile(inputFile, outputFilePath, converter);
converterFile(inputFile, outputFilePath, converter, fileAttribute);
}
}
}

View File

@@ -3,9 +3,9 @@ package cn.keking.service.cache.impl;
import cn.keking.service.cache.CacheService;
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
import com.googlecode.concurrentlinkedhashmap.Weighers;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import javax.annotation.PostConstruct;
import java.util.ArrayList;

View File

@@ -177,6 +177,7 @@ public class CacheServiceRocksDBImpl implements CacheService {
}
@Override
@SuppressWarnings("unchecked")
public Map<String, String> getMediaConvertCache() {
Map<String, String> result = new HashMap<>();
try{
@@ -199,6 +200,7 @@ public class CacheServiceRocksDBImpl implements CacheService {
}
@Override
@SuppressWarnings("unchecked")
public String getMediaConvertCache(String key) {
String result = "";
try{

View File

@@ -3,11 +3,13 @@ package cn.keking.service.impl;
import cn.keking.config.ConfigConstants;
import cn.keking.model.FileAttribute;
import cn.keking.model.ReturnResponse;
import cn.keking.service.FilePreview;
import cn.keking.utils.DownloadUtils;
import cn.keking.service.FileHandlerService;
import cn.keking.service.FilePreview;
import cn.keking.service.OfficeToPdfService;
import cn.keking.utils.DownloadUtils;
import cn.keking.utils.OfficeUtils;
import cn.keking.web.filter.BaseUrlFilter;
import org.artofsolving.jodconverter.office.OfficeException;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
@@ -42,33 +44,83 @@ public class OfficeFilePreviewImpl implements FilePreview {
String baseUrl = BaseUrlFilter.getBaseUrl();
String suffix = fileAttribute.getSuffix();
String fileName = fileAttribute.getName();
boolean isHtml = suffix.equalsIgnoreCase("xls") || suffix.equalsIgnoreCase("xlsx");
String filePassword = fileAttribute.getFilePassword();
String userToken = fileAttribute.getUserToken();
boolean isHtml = suffix.equalsIgnoreCase("xls") || suffix.equalsIgnoreCase("xlsx") || suffix.equalsIgnoreCase("csv");
String pdfName = fileName.substring(0, fileName.lastIndexOf(".") + 1) + (isHtml ? "html" : "pdf");
String outFilePath = FILE_DIR + pdfName;
// 判断之前是否已转换过,如果转换过,直接返回,否则执行转换
if (!fileHandlerService.listConvertedFiles().containsKey(pdfName) || !ConfigConstants.isCacheEnabled()) {
String filePath;
ReturnResponse<String> response = DownloadUtils.downLoad(fileAttribute, null);
String cacheFileName = userToken == null ? pdfName : userToken + "_" + pdfName;
String outFilePath = FILE_DIR + cacheFileName;
// 下载远程文件到本地,如果文件在本地已存在不会重复下载
ReturnResponse<String> response = DownloadUtils.downLoad(fileAttribute, fileName);
if (response.isFailure()) {
return otherFilePreview.notSupportedFile(model, fileAttribute, response.getMsg());
}
filePath = response.getContent();
String filePath = response.getContent();
/*
* 1. 缓存判断-如果文件已经进行转换过,就直接返回,否则执行转换
* 2. 缓存判断-加密文件基于userToken进行缓存如果没有就不缓存
*/
boolean isCached = false;
boolean isUseCached = false;
boolean isPwdProtectedOffice = false;
if (ConfigConstants.isCacheEnabled()) {
// 全局开启缓存
isUseCached = true;
if (fileHandlerService.listConvertedFiles().containsKey(cacheFileName)) {
// 存在缓存
isCached = true;
}
if (OfficeUtils.isPwdProtected(filePath)) {
isPwdProtectedOffice = true;
if (!StringUtils.hasLength(userToken)) {
// 不缓存没有userToken的加密文件
isUseCached = false;
}
}
} else {
isPwdProtectedOffice = OfficeUtils.isPwdProtected(filePath);
}
if (isCached == false) {
// 没有缓存执行转换逻辑
if (isPwdProtectedOffice && !StringUtils.hasLength(filePassword)) {
// 加密文件需要密码
model.addAttribute("needFilePassword", true);
return EXEL_FILE_PREVIEW_PAGE;
} else {
if (StringUtils.hasText(outFilePath)) {
officeToPdfService.openOfficeToPDF(filePath, outFilePath);
try {
officeToPdfService.openOfficeToPDF(filePath, outFilePath, fileAttribute);
} catch (OfficeException e) {
if (isPwdProtectedOffice && OfficeUtils.isCompatible(filePath, filePassword) == false) {
// 加密文件密码错误,提示重新输入
model.addAttribute("needFilePassword", true);
model.addAttribute("filePasswordError", true);
return EXEL_FILE_PREVIEW_PAGE;
}
return otherFilePreview.notSupportedFile(model, fileAttribute, "抱歉,该文件版本不兼容,文件版本错误。");
}
if (isHtml) {
// 对转换后的文件进行操作(改变编码方式)
fileHandlerService.doActionConvertedFile(outFilePath);
}
if (ConfigConstants.isCacheEnabled()) {
if (isUseCached) {
// 加入缓存
fileHandlerService.addConvertedFile(pdfName, fileHandlerService.getRelativePath(outFilePath));
fileHandlerService.addConvertedFile(cacheFileName, fileHandlerService.getRelativePath(outFilePath));
}
}
}
}
if (!isHtml && baseUrl != null && (OFFICE_PREVIEW_TYPE_IMAGE.equals(officePreviewType) || OFFICE_PREVIEW_TYPE_ALL_IMAGES.equals(officePreviewType))) {
return getPreviewType(model, fileAttribute, officePreviewType, baseUrl, pdfName, outFilePath, fileHandlerService, OFFICE_PREVIEW_TYPE_IMAGE, otherFilePreview);
return getPreviewType(model, fileAttribute, officePreviewType, baseUrl, cacheFileName, outFilePath, fileHandlerService, OFFICE_PREVIEW_TYPE_IMAGE, otherFilePreview);
}
model.addAttribute("pdfUrl", pdfName);
model.addAttribute("pdfUrl", cacheFileName);
return isHtml ? EXEL_FILE_PREVIEW_PAGE : PDF_FILE_PREVIEW_PAGE;
}
@@ -88,4 +140,5 @@ public class OfficeFilePreviewImpl implements FilePreview {
return PICTURE_FILE_PREVIEW_PAGE;
}
}
}

View File

@@ -12,6 +12,9 @@ import org.springframework.ui.Model;
import org.springframework.web.util.HtmlUtils;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
/**
* Created by kl on 2018/1/17.
@@ -28,16 +31,14 @@ public class SimTextFilePreviewImpl implements FilePreview {
private static final String FILE_DIR = ConfigConstants.getFileDir();
@Override
public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
String fileName = fileAttribute.getName();
String baseUrll = FILE_DIR + fileName;
// String suffix = fileAttribute.getSuffix();
String filePath = FILE_DIR + fileName;
ReturnResponse<String> response = DownloadUtils.downLoad(fileAttribute, fileName);
if (response.isFailure()) {
return otherFilePreview.notSupportedFile(model, fileAttribute, response.getMsg());
}
try {
String fileData = HtmlUtils.htmlEscape(textData(baseUrll));
String fileData = HtmlUtils.htmlEscape(textData(filePath));
model.addAttribute("textData", Base64.encodeBase64String(fileData.getBytes()));
} catch (IOException e) {
return otherFilePreview.notSupportedFile(model, fileAttribute, e.getLocalizedMessage());
@@ -45,15 +46,16 @@ public class SimTextFilePreviewImpl implements FilePreview {
return TXT_FILE_PREVIEW_PAGE;
}
private String textData(String baseUrll) throws IOException {
File file = new File(baseUrll);
private String textData(String filePath) throws IOException {
File file = new File(filePath);
if (!file.exists() || file.length() == 0) {
String line="";
return line;
return "";
} else {
String charset = EncodingDetects.getJavaEncode(baseUrll);
System.out.println(charset);
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(baseUrll), charset));
String charset = EncodingDetects.getJavaEncode(filePath);
if ("ASCII".equals(charset)) {
charset = StandardCharsets.US_ASCII.name();
}
BufferedReader br = new BufferedReader(new InputStreamReader(Files.newInputStream(Paths.get(filePath)), charset));
StringBuilder result = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {

View File

@@ -8,6 +8,8 @@ import cn.keking.utils.ConvertPicUtil;
import cn.keking.utils.DownloadUtils;
import cn.keking.utils.WebUtils;
import cn.keking.web.filter.BaseUrlFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
@@ -18,12 +20,15 @@ import java.util.List;
/**
* tiff 图片文件处理
*
* @author kl (http://kailing.pub)
* @since 2021/2/8
*/
@Service
public class TiffFilePreviewImpl implements FilePreview {
private final static Logger logger = LoggerFactory.getLogger(TiffFilePreviewImpl.class);
private final PictureFilePreviewImpl pictureFilePreview;
private static final String INITIALIZE_MEMORY_SIZE = "initializeMemorySize";
//默认初始化 50MB 内存
@@ -78,6 +83,7 @@ public class TiffFilePreviewImpl implements FilePreview {
}
// 如果pdf已经存在则将url路径加入到对象中返回给页面
assert filePdf != null;
if (filePdf.exists()) {
String pdfUrl = baseUrl + inputFileNamePrefix + ".pdf";
model.addAttribute("pdfUrl", pdfUrl);
@@ -101,8 +107,8 @@ public class TiffFilePreviewImpl implements FilePreview {
}
// 转换后的tif没用了可以删掉了
if(fileTiff.exists()){
fileTiff.delete();
if (fileTiff.exists() && !fileTiff.delete()) {
logger.error("{} 清理失败", strLocalTif);
}
return PICTURE_FILE_PREVIEW_PAGE;

View File

@@ -27,6 +27,7 @@ public class ConvertPicUtil {
/**
* Tif 转 JPG。
*
* @param strInputFile 输入文件的路径和文件名
* @param strOutputFile 输出文件的路径和文件名
* @return boolean 是否转换成功
@@ -60,8 +61,8 @@ public class ConvertPicUtil {
int intTifCount = imageDecoder.getNumPages();
logger.info("该tif文件共有【" + intTifCount + "】页");
String strJpgPath = "";
String strJpgUrl = "";
String strJpgPath;
String strJpgUrl;
if (intTifCount == 1) {
// 如果是单页tif文件则转换的目标文件夹就在指定的位置
strJpgPath = strOutputFile.substring(0, strOutputFile.lastIndexOf("/"));
@@ -72,13 +73,13 @@ public class ConvertPicUtil {
// 处理目标文件夹,如果不存在则自动创建
File fileJpgPath = new File(strJpgPath);
if (!fileJpgPath.exists()) {
fileJpgPath.mkdirs();
if (!fileJpgPath.exists() && !fileJpgPath.mkdirs()) {
logger.error("{} 创建失败", strJpgPath);
}
// 循环处理每页tif文件转换为jpg
for (int i = 0; i < intTifCount; i++) {
String strJpg = "";
String strJpg;
if (intTifCount == 1) {
strJpg = strJpgPath + "/" + strFilePrefix + ".jpg";
strJpgUrl = strFilePrefix + ".jpg";
@@ -118,21 +119,19 @@ public class ConvertPicUtil {
try {
fileSeekStream.close();
} catch (IOException e) {
}
fileSeekStream = null;
logger.error(e.getMessage(), e);
}
}
}
}
/**
* 将Jpg图片转换为Pdf文件
*
* @param strJpgFile 输入的jpg的路径和文件名
* @param strPdfFile 输出的pdf的路径和文件名
* @return
*/
public static File convertJpg2Pdf(String strJpgFile, String strPdfFile) {
public static void convertJpg2Pdf(String strJpgFile, String strPdfFile) {
Document document = new Document();
// 设置文档页边距
document.setMargins(0, 0, 0, 0);
@@ -157,23 +156,18 @@ public class ConvertPicUtil {
document.add(image);
} catch (Exception ioe) {
ioe.printStackTrace();
return null;
} finally {
//关闭文档
document.close();
try {
assert fos != null;
fos.flush();
fos.close();
File filePDF = new File(strPdfFile);
return filePDF;
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
@@ -182,7 +176,7 @@ public class ConvertPicUtil {
*
* @param strTifFile 输入的tif的路径和文件名
* @param strPdfFile 输出的pdf的路径和文件名
* @return
* @return File
*/
public static File convertTif2Pdf(String strTifFile, String strPdfFile) {
try {
@@ -204,7 +198,7 @@ public class ConvertPicUtil {
List<String> listPic2Jpg = convertTif2Jpg(strTifFile, strJpg);
if (listPic2Jpg != null && fileJpg.exists()) {
filePDF = convertJpg2Pdf(strJpg, strPdfFile);
convertJpg2Pdf(strJpg, strPdfFile);
}
} else {
@@ -229,7 +223,7 @@ public class ConvertPicUtil {
return filePDF;
} catch (Exception e) {
System.out.println(e.toString());
logger.error(e.getMessage(), e);
}
return null;
}

View File

@@ -87,6 +87,13 @@ public class DownloadUtils {
if (!dirFile.exists() && !dirFile.mkdirs()) {
logger.error("创建目录【{}】失败,可能是权限不够,请检查", fileDir);
}
// 文件已在本地存在,跳过文件下载
File realFile = new File(realPath);
if (realFile.exists()) {
fileAttribute.setSkipDownLoad(true);
}
return realPath;
}

View File

@@ -402,7 +402,7 @@ class BytesEncodingDetect extends Encoding {
int row, column;
rawtextlen = rawtext.length;
for (i = 0; i < rawtextlen; i++) {
if (rawtext[i] == '~') {
if (rawtext[i] == '~' && i < rawtextlen - 1) {
if (rawtext[i + 1] == '{') {
hzstart++;
i += 2;

View File

@@ -1,17 +1,18 @@
package cn.keking.utils;
import cn.keking.config.ConfigConstants;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
/**
* @auther: chenjh
@@ -46,7 +47,7 @@ public class FtpUtils {
String remoteFilePath = url.getPath();
LOGGER.debug("FTP connection url:{}, username:{}, password:{}, controlEncoding:{}, localFilePath:{}", ftpUrl, username, password, controlEncoding, localFilePath);
FTPClient ftpClient = connect(host, port, username, password, controlEncoding);
OutputStream outputStream = new FileOutputStream(localFilePath);
OutputStream outputStream = Files.newOutputStream(Paths.get(localFilePath));
ftpClient.enterLocalPassiveMode();
boolean downloadResult = ftpClient.retrieveFile(new String(remoteFilePath.getBytes(controlEncoding), StandardCharsets.ISO_8859_1), outputStream);
LOGGER.debug("FTP download result {}", downloadResult);

View File

@@ -7,6 +7,8 @@ import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class KkFileUtils {
@@ -15,6 +17,33 @@ public class KkFileUtils {
public static final String DEFAULT_FILE_ENCODING = "UTF-8";
private static final List<String> illegalFileStrList = new ArrayList<>();
static {
illegalFileStrList.add("../");
illegalFileStrList.add("./");
illegalFileStrList.add("..\\");
illegalFileStrList.add(".\\");
illegalFileStrList.add("\\..");
illegalFileStrList.add("\\.");
illegalFileStrList.add("..");
illegalFileStrList.add("...");
}
/**
* 检查文件名是否合规
* @param fileName 文件名
* @return 合规结果,true:不合规false:合规
*/
public static boolean isIllegalFileName(String fileName){
for (String str: illegalFileStrList){
if(fileName.contains(str)){
return true;
}
}
return false;
}
/**
* 判断url是否是http资源
*

View File

@@ -0,0 +1,64 @@
package cn.keking.utils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.poi.extractor.ExtractorFactory;
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
import org.springframework.lang.Nullable;
import java.io.FileInputStream;
import java.io.IOException;
/**
* Office工具类
*
* @author ylyue
* @since 2022/7/5
*/
public class OfficeUtils {
private static final String POI_INVALID_PASSWORD_MSG = "Invalid password specified";
/**
* 判断officeword,excel,ppt文件是否受密码保护
*
* @param path office文件路径
* @return 是否受密码保护
*/
public static boolean isPwdProtected(String path) {
try {
ExtractorFactory.createExtractor(new FileInputStream(path));
} catch (IOException e) {
if (POI_INVALID_PASSWORD_MSG.equals(e.getMessage())) {
return true;
}
} catch (Exception e) {
Throwable[] throwableArray = ExceptionUtils.getThrowables(e);
for (Throwable throwable : throwableArray) {
if (throwable instanceof IOException && POI_INVALID_PASSWORD_MSG.equals(throwable.getMessage())) {
return true;
}
}
}
return false;
}
/**
* 判断office文件是否可打开兼容
*
* @param path office文件路径
* @param password 文件密码
* @return 是否可打开(兼容)
*/
public static synchronized boolean isCompatible(String path, @Nullable String password) {
try {
Biff8EncryptionKey.setCurrentUserPassword(password);
ExtractorFactory.createExtractor(new FileInputStream(path));
} catch (Exception e) {
return false;
} finally {
Biff8EncryptionKey.setCurrentUserPassword(null);
}
return true;
}
}

View File

@@ -1,11 +1,17 @@
package cn.keking.utils;
import io.mola.galimatias.GalimatiasParseException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.Base64Utils;
import javax.servlet.ServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
@@ -17,6 +23,7 @@ public class WebUtils {
/**
* 获取标准的URL
*
* @param urlStr url
* @return 标准的URL
*/
@@ -115,10 +122,22 @@ public class WebUtils {
* @return 文件名编码后的url
*/
public static String encodeUrlFileName(String url) {
String encodedFileName;
String fullFileName = WebUtils.getUrlParameterReg(url, "fullfilename");
if (fullFileName != null && fullFileName.length() > 0) {
try {
encodedFileName = URLEncoder.encode(fullFileName, "UTF-8");
} catch (UnsupportedEncodingException e) {
return null;
}
String noQueryUrl = url.substring(0, url.indexOf("?"));
String parameterStr = url.substring(url.indexOf("?"));
parameterStr = parameterStr.replaceFirst(fullFileName, encodedFileName);
return noQueryUrl + parameterStr;
}
String noQueryUrl = url.substring(0, url.contains("?") ? url.indexOf("?") : url.length());
int fileNameStartIndex = noQueryUrl.lastIndexOf('/') + 1;
int fileNameEndIndex = noQueryUrl.lastIndexOf('.');
String encodedFileName;
try {
encodedFileName = URLEncoder.encode(noQueryUrl.substring(fileNameStartIndex, fileNameEndIndex), "UTF-8");
} catch (UnsupportedEncodingException e) {
@@ -126,4 +145,80 @@ public class WebUtils {
}
return url.substring(0, fileNameStartIndex) + encodedFileName + url.substring(fileNameEndIndex);
}
/**
* 从 ServletRequest 获取预览的源 url , 已 base64 解码
*
* @param request 请求 request
* @return url
*/
public static String getSourceUrl(ServletRequest request) {
String url = request.getParameter("url");
String urls = request.getParameter("urls");
String currentUrl = request.getParameter("currentUrl");
String urlPath = request.getParameter("urlPath");
if (StringUtils.isNotBlank(url)) {
return decodeUrl(url);
}
if (StringUtils.isNotBlank(currentUrl)) {
return decodeUrl(currentUrl);
}
if (StringUtils.isNotBlank(urlPath)) {
return decodeUrl(urlPath);
}
if (StringUtils.isNotBlank(urls)) {
urls = decodeUrl(urls);
String[] images = urls.split("\\|");
return images[0];
}
return null;
}
/**
* 将 Base64 字符串解码再解码URL参数, 默认使用 UTF-8
* @param source 原始 Base64 字符串
* @return decoded string
*
* aHR0cHM6Ly9maWxlLmtla2luZy5jbi9kZW1vL%2BS4reaWhy5wcHR4 -> https://file.keking.cn/demo/%E4%B8%AD%E6%96%87.pptx -> https://file.keking.cn/demo/中文.pptx
*/
public static String decodeUrl(String source) {
String url = decodeBase64String(source, StandardCharsets.UTF_8);
try {
url = URLDecoder.decode(url, StandardCharsets.UTF_8.name());
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
return url;
}
/**
* 将 Base64 字符串使用指定字符集解码
* @param source 原始 Base64 字符串
* @param charsets 字符集
* @return decoded string
*/
public static String decodeBase64String(String source, Charset charsets) {
/*
* url 传入的参数里加号会被替换成空格,导致解析出错,这里需要把空格替换回加号
* 有些 Base64 实现可能每 76 个字符插入换行符,也一并去掉
* https://github.com/kekingcn/kkFileView/pull/340
*/
return new String(Base64Utils.decodeFromString(
source.replaceAll(" ", "+").replaceAll("\n", "")
), charsets);
}
/**
* 获取 url 的 host
* @param urlStr url
* @return host
*/
public static String getHost(String urlStr) {
try {
URL url = new URL(urlStr);
return url.getHost().toLowerCase();
} catch (MalformedURLException ignored) {
}
return null;
}
}

View File

@@ -1,26 +1,35 @@
package cn.keking.web.controller;
import cn.keking.config.ConfigConstants;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import cn.keking.model.ReturnResponse;
import cn.keking.utils.KkFileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import org.springframework.web.util.HtmlUtils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
*
* @author yudian-it
* @date 2017/12/1
*/
@@ -33,16 +42,17 @@ public class FileController {
private final String demoDir = "demo";
private final String demoPath = demoDir + File.separator;
@RequestMapping(value = "fileUpload", method = RequestMethod.POST)
public String fileUpload(@RequestParam("file") MultipartFile file) throws JsonProcessingException {
@PostMapping("/fileUpload")
public ReturnResponse<Object> fileUpload(@RequestParam("file") MultipartFile file) {
if (ConfigConstants.getFileUploadDisable()) {
return new ObjectMapper().writeValueAsString(ReturnResponse.failure("文件传接口已禁用"));
return ReturnResponse.failure("文件传接口已禁用");
}
// 获取文件名
String fileName = file.getOriginalFilename();
//判断是否为IE浏览器的文件名IE浏览器下文件名会带有盘符信息
// escaping dangerous characters to prevent XSS
assert fileName != null;
fileName = HtmlUtils.htmlEscape(fileName, StandardCharsets.UTF_8.name());
// Check for Unix-style path
@@ -56,37 +66,50 @@ public class FileController {
}
// 判断是否存在同名文件
if (existsFile(fileName)) {
return new ObjectMapper().writeValueAsString(ReturnResponse.failure("存在同名文件,请先删除原有文件再次上传"));
return ReturnResponse.failure("存在同名文件,请先删除原有文件再次上传");
}
File outFile = new File(fileDir + demoPath);
if (!outFile.exists() && !outFile.mkdirs()) {
logger.error("创建文件夹【{}】失败,请检查目录权限!", fileDir + demoPath);
}
logger.info("上传文件:{}", fileDir + demoPath + fileName);
try(InputStream in = file.getInputStream(); OutputStream out = new FileOutputStream(fileDir + demoPath + fileName)) {
try (InputStream in = file.getInputStream(); OutputStream out = Files.newOutputStream(Paths.get(fileDir + demoPath + fileName))) {
StreamUtils.copy(in, out);
return new ObjectMapper().writeValueAsString(ReturnResponse.success(null));
return ReturnResponse.success(null);
} catch (IOException e) {
logger.error("文件上传失败", e);
return new ObjectMapper().writeValueAsString(ReturnResponse.failure());
return ReturnResponse.failure();
}
}
@RequestMapping(value = "deleteFile", method = RequestMethod.GET)
public String deleteFile(String fileName) throws JsonProcessingException {
@GetMapping("/deleteFile")
public ReturnResponse<Object> deleteFile(String fileName) {
if (fileName == null || fileName.length() == 0) {
return ReturnResponse.failure("文件名为空,删除失败!");
}
try {
fileName = URLDecoder.decode(fileName, StandardCharsets.UTF_8.name());
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
if (fileName.contains("/")) {
fileName = fileName.substring(fileName.lastIndexOf("/") + 1);
}
if (KkFileUtils.isIllegalFileName(fileName)) {
return ReturnResponse.failure("非法文件名,删除失败!");
}
File file = new File(fileDir + demoPath + fileName);
logger.info("删除文件:{}", file.getAbsolutePath());
if (file.exists() && !file.delete()) {
logger.error("删除文件【{}】失败,请检查目录权限!",file.getPath());
String msg = String.format("删除文件【%s】失败,请检查目录权限!", file.getPath());
logger.error(msg);
return ReturnResponse.failure(msg);
}
return new ObjectMapper().writeValueAsString(ReturnResponse.success());
return ReturnResponse.success();
}
@RequestMapping(value = "listFiles", method = RequestMethod.GET)
public String getFiles() throws JsonProcessingException {
@GetMapping("/listFiles")
public List<Map<String, String>> getFiles() {
List<Map<String, String>> list = new ArrayList<>();
File file = new File(fileDir + demoPath);
if (file.exists()) {
@@ -96,7 +119,7 @@ public class FileController {
list.add(fileName);
});
}
return new ObjectMapper().writeValueAsString(list);
return list;
}
private boolean existsFile(String fileName) {

View File

@@ -1,8 +1,7 @@
package cn.keking.web.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.GetMapping;
/**
* 页面跳转
@@ -12,12 +11,22 @@ import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class IndexController {
@RequestMapping(value = "/index", method = RequestMethod.GET)
@GetMapping( "/index")
public String go2Index(){
return "index";
}
@RequestMapping(value = "/", method = RequestMethod.GET)
@GetMapping( "/record")
public String go2Record(){
return "record";
}
@GetMapping( "/comment")
public String go2Comment(){
return "comment";
}
@GetMapping( "/")
public String root() {
return "redirect:/index";
}

View File

@@ -1,37 +1,32 @@
package cn.keking.web.controller;
import cn.keking.config.ConfigConstants;
import cn.keking.model.FileAttribute;
import cn.keking.service.FileHandlerService;
import cn.keking.service.FilePreview;
import cn.keking.service.FilePreviewFactory;
import cn.keking.service.cache.CacheService;
import cn.keking.service.impl.OtherFilePreviewImpl;
import cn.keking.service.FileHandlerService;
import cn.keking.utils.WebUtils;
import fr.opensagres.xdocreport.core.io.IOUtils;
import io.mola.galimatias.GalimatiasParseException;
import jodd.io.NetUtil;
import org.apache.commons.codec.binary.Base64;
import org.artofsolving.jodconverter.util.PlatformUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.util.HtmlUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import static cn.keking.service.FilePreview.PICTURE_FILE_PREVIEW_PAGE;
@@ -56,18 +51,19 @@ public class OnlinePreviewController {
this.otherFilePreview = otherFilePreview;
}
@RequestMapping(value = "/onlinePreview")
@GetMapping( "/onlinePreview")
public String onlinePreview(String url, Model model, HttpServletRequest req) {
if (url == null || url.length() == 0){
logger.info("URL异常{}", url);
return otherFilePreview.notSupportedFile(model, "NULL地址不允许预览");
}
String fileUrl;
try {
fileUrl = new String(Base64.decodeBase64(url), StandardCharsets.UTF_8);
fileUrl = WebUtils.decodeUrl(url);
} catch (Exception ex) {
String errorMsg = String.format(BASE64_DECODE_ERROR_MSG, "url");
return otherFilePreview.notSupportedFile(model, errorMsg);
}
if (!allowPreview(fileUrl)) {
return otherFilePreview.notSupportedFile(model, "该文件不允许预览:" + fileUrl);
}
FileAttribute fileAttribute = fileHandlerService.getFileAttribute(fileUrl, req);
model.addAttribute("file", fileAttribute);
FilePreview filePreview = previewFactory.get(fileAttribute);
@@ -75,11 +71,17 @@ public class OnlinePreviewController {
return filePreview.filePreviewHandle(fileUrl, model, fileAttribute);
}
@RequestMapping(value = "/picturesPreview")
public String picturesPreview(String urls, Model model, HttpServletRequest req) throws UnsupportedEncodingException {
@GetMapping( "/picturesPreview")
public String picturesPreview(String urls, Model model, HttpServletRequest req) {
if (urls == null || urls.length() == 0){
logger.info("URL异常{}", urls);
return otherFilePreview.notSupportedFile(model, "NULL地址不允许预览");
}
String fileUrls;
try {
fileUrls = new String(Base64.decodeBase64(urls));
fileUrls = WebUtils.decodeUrl(urls);
// 防止XSS攻击
fileUrls = HtmlUtils.htmlEscape(fileUrls);
} catch (Exception ex) {
String errorMsg = String.format(BASE64_DECODE_ERROR_MSG, "urls");
return otherFilePreview.notSupportedFile(model, errorMsg);
@@ -89,18 +91,11 @@ public class OnlinePreviewController {
String[] images = fileUrls.split("\\|");
List<String> imgUrls = Arrays.asList(images);
model.addAttribute("imgUrls", imgUrls);
String currentUrl = req.getParameter("currentUrl");
if (StringUtils.hasText(currentUrl)) {
String decodedCurrentUrl = new String(Base64.decodeBase64(currentUrl));
if (!allowPreview(decodedCurrentUrl)) {
return otherFilePreview.notSupportedFile(model, "该文件不允许预览:" + decodedCurrentUrl);
}
model.addAttribute("currentUrl", decodedCurrentUrl);
} else {
if (!allowPreview(imgUrls.get(0))) {
return otherFilePreview.notSupportedFile(model, "该文件不允许预览:" + imgUrls.get(0));
}
model.addAttribute("currentUrl", imgUrls.get(0));
}
return PICTURE_FILE_PREVIEW_PAGE;
@@ -113,21 +108,71 @@ public class OnlinePreviewController {
* @param urlPath url
* @param response response
*/
@RequestMapping(value = "/getCorsFile", method = RequestMethod.GET)
public void getCorsFile(String urlPath, HttpServletResponse response) {
logger.info("下载跨域pdf文件url{}", urlPath);
try {
URL url = WebUtils.normalizedURL(urlPath);
if (!allowPreview(urlPath)) {
response.setHeader("content-type", "text/html;charset=utf-8");
response.getOutputStream().println("forbidden");
response.setStatus(401);
@GetMapping("/getCorsFile")
public void getCorsFile(String urlPath, HttpServletResponse response) throws IOException {
if (urlPath == null || urlPath.length() == 0){
logger.info("URL异常{}", urlPath);
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
response.setHeader("Content-Type", "text/html; charset=UTF-8");
response.getWriter().println("NULL地址不允许预览");
return;
}
byte[] bytes = NetUtil.downloadBytes(url.toString());
IOUtils.write(bytes, response.getOutputStream());
try {
urlPath = WebUtils.decodeUrl(urlPath);
} catch (Exception ex) {
logger.error(String.format(BASE64_DECODE_ERROR_MSG, urlPath),ex);
return;
}
HttpURLConnection urlcon;
InputStream inputStream = null;
if (urlPath.toLowerCase().startsWith("file:") || urlPath.toLowerCase().startsWith("file%3")) {
logger.info("读取跨域文件异常可能存在非法访问urlPath{}", urlPath);
return;
}
logger.info("下载跨域pdf文件url{}", urlPath);
if (!urlPath.toLowerCase().startsWith("ftp:")){
try {
URL url = WebUtils.normalizedURL(urlPath);
urlcon=(HttpURLConnection)url.openConnection();
urlcon.setConnectTimeout(30000);
urlcon.setReadTimeout(30000);
urlcon.setInstanceFollowRedirects(false);
if (urlcon.getResponseCode() == 302 || urlcon.getResponseCode() == 301) {
urlcon.disconnect();
url =new URL(urlcon.getHeaderField("Location"));
urlcon=(HttpURLConnection)url.openConnection();
}
if (urlcon.getResponseCode() == 404 || urlcon.getResponseCode() == 403 || urlcon.getResponseCode() == 500 ) {
logger.error("读取跨域文件异常url{}", urlPath);
return ;
} else {
if(urlPath.contains( ".svg")) {
response.setContentType("image/svg+xml");
}
inputStream=(url).openStream();
IOUtils.copy(inputStream, response.getOutputStream());
urlcon.disconnect();
}
} catch (IOException | GalimatiasParseException e) {
logger.error("下载跨域pdf文件异常url{}", urlPath, e);
logger.error("读取跨域文件异常url{}", urlPath);
return ;
} finally {
IOUtils.closeQuietly(inputStream);
}
} else {
try {
URL url = WebUtils.normalizedURL(urlPath);
if(urlPath.contains(".svg")) {
response.setContentType("image/svg+xml");
}
inputStream = (url).openStream();
IOUtils.copy(inputStream, response.getOutputStream());
} catch (IOException | GalimatiasParseException e) {
logger.error("读取跨域文件异常url{}", urlPath);
return ;
} finally {
IOUtils.closeQuietly(inputStream);
}
}
}
@@ -136,32 +181,11 @@ public class OnlinePreviewController {
*
* @param url 请编码后在入队
*/
@RequestMapping("/addTask")
@GetMapping("/addTask")
@ResponseBody
public String addQueueTask(String url) {
logger.info("添加转码队列url{}", url);
cacheService.addQueueTask(url);
return "success";
}
private boolean allowPreview(String urlPath) {
try {
URL url = WebUtils.normalizedURL(urlPath);
if ("file".equals(url.getProtocol().toLowerCase(Locale.ROOT))) {
String filePath = URLDecoder.decode(url.getPath(), StandardCharsets.UTF_8.name());
if (PlatformUtils.isWindows()) {
filePath = filePath.replaceAll("/", "\\\\");
}
filePath = filePath.substring(1);
if (!filePath.startsWith(ConfigConstants.getFileDir()) && !filePath.startsWith(ConfigConstants.getLocalPreviewDir())) {
return false;
}
}
return true;
} catch (IOException | GalimatiasParseException e) {
logger.error("解析URL异常url{}", urlPath, e);
return false;
}
}
}

View File

@@ -48,15 +48,24 @@ public class AttributeSetFilter implements Filter {
private void setWatermarkAttribute(ServletRequest request) {
String watermarkTxt = request.getParameter("watermarkTxt");
request.setAttribute("watermarkTxt", watermarkTxt != null ? watermarkTxt : WatermarkConfigConstants.getWatermarkTxt());
request.setAttribute("watermarkXSpace", WatermarkConfigConstants.getWatermarkXSpace());
request.setAttribute("watermarkYSpace", WatermarkConfigConstants.getWatermarkYSpace());
request.setAttribute("watermarkFont", WatermarkConfigConstants.getWatermarkFont());
request.setAttribute("watermarkFontsize", WatermarkConfigConstants.getWatermarkFontsize());
request.setAttribute("watermarkColor", WatermarkConfigConstants.getWatermarkColor());
request.setAttribute("watermarkAlpha", WatermarkConfigConstants.getWatermarkAlpha());
request.setAttribute("watermarkWidth", WatermarkConfigConstants.getWatermarkWidth());
request.setAttribute("watermarkHeight", WatermarkConfigConstants.getWatermarkHeight());
request.setAttribute("watermarkAngle", WatermarkConfigConstants.getWatermarkAngle());
String watermarkXSpace = request.getParameter("watermarkXSpace");
request.setAttribute("watermarkXSpace", watermarkXSpace != null ? watermarkXSpace : WatermarkConfigConstants.getWatermarkXSpace());
String watermarkYSpace = request.getParameter("watermarkYSpace");
request.setAttribute("watermarkYSpace", watermarkYSpace != null ? watermarkYSpace : WatermarkConfigConstants.getWatermarkYSpace());
String watermarkFont = request.getParameter("watermarkFont");
request.setAttribute("watermarkFont", watermarkFont != null ? watermarkFont : WatermarkConfigConstants.getWatermarkFont());
String watermarkFontsize = request.getParameter("watermarkFontsize");
request.setAttribute("watermarkFontsize", watermarkFontsize != null ? watermarkFontsize : WatermarkConfigConstants.getWatermarkFontsize());
String watermarkColor = request.getParameter("watermarkColor");
request.setAttribute("watermarkColor", watermarkColor != null ? watermarkColor : WatermarkConfigConstants.getWatermarkColor());
String watermarkAlpha = request.getParameter("watermarkAlpha");
request.setAttribute("watermarkAlpha", watermarkAlpha != null ? watermarkAlpha : WatermarkConfigConstants.getWatermarkAlpha());
String watermarkWidth = request.getParameter("watermarkWidth");
request.setAttribute("watermarkWidth", watermarkWidth != null ? watermarkWidth : WatermarkConfigConstants.getWatermarkWidth());
String watermarkHeight = request.getParameter("watermarkHeight");
request.setAttribute("watermarkHeight", watermarkHeight != null ? watermarkHeight : WatermarkConfigConstants.getWatermarkHeight());
String watermarkAngle = request.getParameter("watermarkAngle");
request.setAttribute("watermarkAngle", watermarkAngle != null ? watermarkAngle : WatermarkConfigConstants.getWatermarkAngle());
}
@Override

View File

@@ -1,6 +1,7 @@
package cn.keking.web.filter;
import cn.keking.config.ConfigConstants;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import javax.servlet.*;
@@ -33,19 +34,28 @@ public class BaseUrlFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
String baseUrl;
StringBuilder pathBuilder = new StringBuilder();
pathBuilder.append(request.getScheme()).append("://").append(request.getServerName()).append(":")
.append(request.getServerPort()).append(((HttpServletRequest) request).getContextPath()).append("/");
String baseUrlTmp = ConfigConstants.getBaseUrl();
if (baseUrlTmp != null && !ConfigConstants.DEFAULT_BASE_URL.equalsIgnoreCase(baseUrlTmp)) {
if (!baseUrlTmp.endsWith("/")) {
baseUrlTmp = baseUrlTmp.concat("/");
}
baseUrl = baseUrlTmp;
String configBaseUrl = ConfigConstants.getBaseUrl();
final HttpServletRequest servletRequest = (HttpServletRequest) request;
//1、支持通过 http header 中 X-Base-Url 来动态设置 baseUrl 以支持多个域名/项目的共享使用
final String urlInHeader = servletRequest.getHeader("X-Base-Url");
if (StringUtils.isNotEmpty(urlInHeader)) {
baseUrl = urlInHeader;
} else if (configBaseUrl != null && !ConfigConstants.DEFAULT_BASE_URL.equalsIgnoreCase(configBaseUrl)) {
//2、如果配置文件中配置了 baseUrl 且不为 default 则以配置文件为准
baseUrl = configBaseUrl;
} else {
baseUrl = pathBuilder.toString();
//3、默认动态拼接 baseUrl
baseUrl = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
+ servletRequest.getContextPath() + "/";
}
if (!baseUrl.endsWith("/")) {
baseUrl = baseUrl.concat("/");
}
BASE_URL = baseUrl;
request.setAttribute("baseUrl", baseUrl);
filterChain.doFilter(request, response);

Some files were not shown because too many files have changed in this diff Show More