Compare commits

...

43 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
101 changed files with 48537 additions and 10599 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

@@ -1,53 +0,0 @@
version: '1.0'
name: branch-pipeline
displayName: BranchPipeline
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.3.9
# 构建命令
commands:
- mvn -B clean package -Dmaven.test.skip=true
# 非必填字段开启后表示将构建产物暂存但不会上传到制品库中7天后自动清除
artifacts:
# 构建产物名字作为产物的唯一标识可向下传递支持自定义默认为BUILD_ARTIFACT在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
- name: BUILD_ARTIFACT
# 构建产物获取路径是指代码编译完毕之后构建物的所在路径如通常jar包在target目录下当前目录为代码库根目录
path:
- ./server/target
- step: publish@general_artifacts
name: publish_general_artifacts
displayName: 上传制品
# 上游构建任务定义的产物名默认BUILD_ARTIFACT
dependArtifact: BUILD_ARTIFACT
# 上传到制品库时的制品命名默认output
artifactName: output
dependsOn: build_maven
- stage:
name: release
displayName: 发布
steps:
- step: publish@release_artifacts
name: publish_release_artifacts
displayName: '发布'
# 上游上传制品任务的产出
dependArtifact: output
# 发布制品版本号
version: '1.0.0.0'
# 是否开启版本号自增默认开启
autoIncrement: true
triggers:
push:
branches:
exclude:
- master
include:
- .*

View File

@@ -12,7 +12,7 @@ stages:
# 支持67891011六个版本
jdkVersion: 8
# 支持2.2.13.2.53.3.93.5.23.5.33.5.43.6.13.6.3八个版本
mavenVersion: 3.3.9
mavenVersion: 3.6.3
# 构建命令
commands:
- mvn -B clean package -Dmaven.test.skip=true
@@ -22,28 +22,8 @@ stages:
- name: BUILD_ARTIFACT
# 构建产物获取路径是指代码编译完毕之后构建物的所在路径如通常jar包在target目录下当前目录为代码库根目录
path:
- ./server/target
- step: publish@general_artifacts
name: publish_general_artifacts
displayName: 上传制品
# 上游构建任务定义的产物名默认BUILD_ARTIFACT
dependArtifact: BUILD_ARTIFACT
# 上传到制品库时的制品命名默认output
artifactName: output
dependsOn: build_maven
- stage:
name: release
displayName: 发布
steps:
- step: publish@release_artifacts
name: publish_release_artifacts
displayName: '发布'
# 上游上传制品任务的产出
dependArtifact: output
# 发布制品版本号
version: '1.0.0.0'
# 是否开启版本号自增默认开启
autoIncrement: true
- ./server/target/kkFileView-*.tar.gz
- ./server/target/kkFileView-*.zip
triggers:
push:
branches:

View File

@@ -1,40 +0,0 @@
version: '1.0'
name: pr-pipeline
displayName: PRPipeline
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.3.9
# 构建命令
commands:
- mvn -B clean package -Dmaven.test.skip=true
# 非必填字段开启后表示将构建产物暂存但不会上传到制品库中7天后自动清除
artifacts:
# 构建产物名字作为产物的唯一标识可向下传递支持自定义默认为BUILD_ARTIFACT在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
- name: BUILD_ARTIFACT
# 构建产物获取路径是指代码编译完毕之后构建物的所在路径如通常jar包在target目录下当前目录为代码库根目录
path:
- ./server/target
- step: publish@general_artifacts
name: publish_general_artifacts
displayName: 上传制品
# 上游构建任务定义的产物名默认BUILD_ARTIFACT
dependArtifact: BUILD_ARTIFACT
# 构建产物制品库默认default系统默认创建
artifactRepository: default
# 上传到制品库时的制品命名默认output
artifactName: output
dependsOn: build_maven
triggers:
pr:
branches:
include:
- master

View File

@@ -1,36 +0,0 @@
version: '1.0'
name: pipeline-20220716
displayName: pipeline-20220716
triggers:
trigger: manual
push:
branches:
prefix:
- ''
stages:
- name: stage-8b46aafe
displayName: 未命名
strategy: naturally
trigger: auto
executor: []
steps:
- step: build@maven
name: build_maven
displayName: Maven 构建
jdkVersion: '8'
mavenVersion: 3.3.9
commands:
- mvn -B clean package -Dmaven.test.skip=true
artifacts:
- name: BUILD_ARTIFACT
path:
- ./server/target
settings: []
caches:
- ~/.m2
notify: []
strategy:
retry: '0'
permissions:
- role: admin
members: []

View File

@@ -1,5 +1,5 @@
FROM keking/kkfileview-jdk:4.1.1
MAINTAINER chenjh "842761733@qq.com"
ADD server/target/kkFileView-*.tar.gz /opt/
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

@@ -2,28 +2,28 @@ FROM ubuntu:20.04
MAINTAINER chenjh "842761733@qq.com"
# 内置一些常用的中文字体,避免普遍性乱码
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 &&\
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 && apt-get install -y language-pack-zh-hans &&\
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 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 &&\
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 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 &&\
# 安装 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 &&\
@@ -35,4 +35,4 @@ 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
ENTRYPOINT ["java","-version"]
CMD ["/bin/bash"]

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>office-plugin</artifactId>
@@ -61,6 +61,7 @@
<plugins>
<!-- 要将源码放上去需要加入这个插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1</version>
<configuration>
@@ -121,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

@@ -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();
}
@@ -122,5 +123,5 @@ public class Convert {
officeManager.stop();
}
}
}

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

@@ -15,7 +15,7 @@ public class FileProperties {
}
public Map<String, Object> toMap() {
Map<String, Object> map = new HashMap();
Map<String, Object> map = new HashMap<>();
if (filePassword != null) {
map.put("Password", 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();
@@ -163,9 +164,9 @@ class OfficeProcess {
}
private class ExitCodeRetryable extends Retryable {
private int exitCode;
protected void attempt() throws TemporaryException, Exception {
try {
exitCode = process.exitValue();
@@ -173,7 +174,7 @@ class OfficeProcess {
throw new TemporaryException(illegalThreadStateException);
}
}
public int getExitCode() {
return exitCode;
}

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,11 +26,10 @@ 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 {
private static final Pattern PS_OUTPUT_LINE = Pattern.compile("^\\s*(\\d+)\\s+(.*)$");
private static final Pattern PS_OUTPUT_LINE = Pattern.compile("^\\s*(\\d+)\\s+(.*)$");
private String[] runAsArgs;
@@ -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>
@@ -55,22 +55,22 @@
<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.17</version>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
<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>
@@ -81,12 +81,12 @@
<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 -->
@@ -94,96 +94,111 @@
<dependency>
<groupId>net.sf.sevenzipjbinding</groupId>
<artifactId>sevenzipjbinding</artifactId>
<version>16.02-2.01</version>
<version>${sevenzipjbinding.version}</version>
</dependency>
<dependency>
<groupId>net.sf.sevenzipjbinding</groupId>
<artifactId>sevenzipjbinding-all-platforms</artifactId>
<version>16.02-2.01</version>
<version>${sevenzipjbinding.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.2.0</version>
<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>1.2</version>
<version>${commons-cli.version}</version>
</dependency>
<!-- FTP -->
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.6</version>
<version>${commons-net.version}</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.18</version>
<version>${xstream.version}</version>
</dependency>
<dependency>
<groupId>com.googlecode.concurrentlinkedhashmap</groupId>
<artifactId>concurrentlinkedhashmap-lru</artifactId>
<version>1.4.2</version>
<version>${concurrentlinkedhashmap.version}</version>
</dependency>
<dependency>
<groupId>org.rocksdb</groupId>
<artifactId>rocksdbjni</artifactId>
<version>5.17.2</version>
<version>${rocksdb.version}</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.24</version>
<version>${pdfbox.version}</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox-tools</artifactId>
<version>2.0.15</version>
<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>${basedir}/lib/aspose-cad-19.9.jar</systemPath>
<systemPath>${pom.basedir}/lib/aspose-cad-19.9.jar</systemPath>
</dependency>
<!-- 编码识别 -->
<dependency>
@@ -191,68 +206,68 @@
<artifactId>cpdetector</artifactId>
<version>1.04</version>
<scope>system</scope>
<systemPath>${basedir}/lib/cpdetector-1.04.jar</systemPath>
<systemPath>${pom.basedir}/lib/cpdetector-1.04.jar</systemPath>
</dependency>
<!-- url 规范化 -->
<dependency>
<groupId>io.mola.galimatias</groupId>
<artifactId>galimatias</artifactId>
<version>0.2.1</version>
<version>${galimatias.version}</version>
</dependency>
<!-- 以下是bytedeco 基于opencv ffmpeg封装的javacv用于视频处理 -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.5.2</version>
<version>${bytedeco.version}</version>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId>
<version>1.5.2</version>
<version>${bytedeco.version}</version>
</dependency>
<!-- 此版本中主要兼容linux和windows系统如需兼容其他系统平台请引入对应依赖即可 -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv</artifactId>
<version>4.1.2-1.5.2</version>
<version>${opencv.version}</version>
<classifier>linux-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv</artifactId>
<version>4.1.2-1.5.2</version>
<version>${opencv.version}</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
<version>0.3.6-1.5.1</version>
<version>${openblas.version}</version>
<classifier>linux-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
<version>0.3.6-1.5.1</version>
<version>${openblas.version}</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg</artifactId>
<version>4.2.1-1.5.2</version>
<version>${ffmpeg.version}</version>
<classifier>linux-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg</artifactId>
<version>4.2.1-1.5.2</version>
<version>${ffmpeg.version}</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>com.lowagie</groupId>
<artifactId>itext</artifactId>
<version>2.1.7</version>
<version>${itext.version}</version>
</dependency>
<dependency>
@@ -260,14 +275,14 @@
<artifactId>jai_core</artifactId>
<version>1.1.3</version>
<scope>system</scope>
<systemPath>${basedir}/lib/jai_core-1.1.3.jar</systemPath>
<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>${basedir}/lib/jai_codec-1.1.3.jar</systemPath>
<systemPath>${pom.basedir}/lib/jai_codec-1.1.3.jar</systemPath>
</dependency>
<!-- test dependency - start -->
@@ -279,7 +294,7 @@
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
<version>${httpclient.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
@@ -322,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>

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
@@ -33,4 +33,4 @@ if [ -f "/etc/redhat-release" ]; then
else
apt-get install -y wget
install_ubuntu
fi
fi

View File

@@ -4,6 +4,7 @@ cd "%KKFILEVIEW_BIN_FOLDER%"
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 homesite: https://kkFileView.keking.cn
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)
@@ -32,7 +32,7 @@ else
grep 'office\.home' ../config/application.properties | grep '!^#'
if [ $? -eq 0 ]; then
echo "Using customized office.home"
else
else
for i in ${DIR_HOME[@]}
do
if [ -f "$i/program/soffice.bin" ]; then
@@ -42,18 +42,19 @@ else
fi
done
if [ ! -n "${FLAG}" ]; then
echo "Installing OpenOffice"
echo "Installing LibreOffice"
sh ./install.sh
else
else
echo "Detected office component has been installed in $OFFICE_HOME"
fi
fi
## 启动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 homesite: https://kkFileView.keking.cn"
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

@@ -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

@@ -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) {
@@ -286,7 +286,7 @@ public class ConfigConstants {
return pdfPrintDisable;
}
@Value("${pdf.print.disable:true}")
public void setPdfPrintDisable(String pdfPrintDisable) {
public void setPdfPrintDisable(String pdfPrintDisable) {
setPdfPrintDisableValue(pdfPrintDisable);
}
public static void setPdfPrintDisableValue(String pdfPrintDisable) {
@@ -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

@@ -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));
}
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);
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;
}
// 开启新的线程处理文件解压
executors.submit(new ZipExtractorWorker(entriesToBeExtracted, zipFile, filePath));
fileHandlerService.putImgCache(fileKey, imgUrls);
return new ObjectMapper().writeValueAsString(appender.get(""));
} catch (IOException e) {
e.printStackTrace();
return null;
utfBytes[k++] = (byte) (0xe0 | (m >> 12));
utfBytes[k++] = (byte) (0x80 | ((m >> 6) & 0x3f));
utfBytes[k++] = (byte) (0x80 | (m & 0x3f));
}
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);
}
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();
}
}
sortedEntries.sort(Comparator.comparingInt(o -> o.getName().length()));
return Collections.enumeration(sortedEntries);
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) {

View File

@@ -120,7 +120,7 @@ public class OfficePluginManager {
baos.write(b);
}
String s = baos.toString();
if (!"0".equals(s)) {
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;

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

@@ -46,7 +46,7 @@ public class OfficeFilePreviewImpl implements FilePreview {
String fileName = fileAttribute.getName();
String filePassword = fileAttribute.getFilePassword();
String userToken = fileAttribute.getUserToken();
boolean isHtml = suffix.equalsIgnoreCase("xls") || suffix.equalsIgnoreCase("xlsx");
boolean isHtml = suffix.equalsIgnoreCase("xls") || suffix.equalsIgnoreCase("xlsx") || suffix.equalsIgnoreCase("csv");
String pdfName = fileName.substring(0, fileName.lastIndexOf(".") + 1) + (isHtml ? "html" : "pdf");
String cacheFileName = userToken == null ? pdfName : userToken + "_" + pdfName;
String outFilePath = FILE_DIR + cacheFileName;

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);
if(!file.exists() || file.length() == 0) {
String line="";
return line;
}else {
String charset = EncodingDetects.getJavaEncode(baseUrll);
System.out.println(charset);
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(baseUrll), charset));
private String textData(String filePath) throws IOException {
File file = new File(filePath);
if (!file.exists() || file.length() == 0) {
return "";
} else {
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 内存
@@ -43,25 +48,25 @@ public class TiffFilePreviewImpl implements FilePreview {
tifPreviewType = tifOnLinePreviewType;
}
if("tif".equalsIgnoreCase(tifPreviewType)){
if ("tif".equalsIgnoreCase(tifPreviewType)) {
pictureFilePreview.filePreviewHandle(url,model,fileAttribute);
String fileSize = WebUtils.getUrlParameterReg(url,INITIALIZE_MEMORY_SIZE);
if(StringUtils.hasText(fileSize)){
model.addAttribute(INITIALIZE_MEMORY_SIZE,fileSize);
}else {
model.addAttribute(INITIALIZE_MEMORY_SIZE,Long.toString(INITIALIZE_MEMORY_SIZE_VALUE_DEFAULT));
pictureFilePreview.filePreviewHandle(url, model, fileAttribute);
String fileSize = WebUtils.getUrlParameterReg(url, INITIALIZE_MEMORY_SIZE);
if (StringUtils.hasText(fileSize)) {
model.addAttribute(INITIALIZE_MEMORY_SIZE, fileSize);
} else {
model.addAttribute(INITIALIZE_MEMORY_SIZE, Long.toString(INITIALIZE_MEMORY_SIZE_VALUE_DEFAULT));
}
return TIFF_FILE_PREVIEW_PAGE;
}else if("jpg".equalsIgnoreCase(tifPreviewType) || "pdf".equalsIgnoreCase(tifPreviewType)){
} else if ("jpg".equalsIgnoreCase(tifPreviewType) || "pdf".equalsIgnoreCase(tifPreviewType)) {
String inputFileName = url.substring(url.lastIndexOf("/") + 1);
String inputFileNamePrefix = inputFileName.substring(0, inputFileName.lastIndexOf("."));
String strLocalTif = fileDir + inputFileName;
File fileTiff = new File(strLocalTif);
// 如果本地不存在这个tif文件则下载
if(!fileTiff.exists()){
if (!fileTiff.exists()) {
ReturnResponse<String> response = DownloadUtils.downLoad(fileAttribute, inputFileName);
if (response.isFailure()) {
return NOT_SUPPORTED_FILE_PAGE;
@@ -69,22 +74,23 @@ public class TiffFilePreviewImpl implements FilePreview {
}
String baseUrl = BaseUrlFilter.getBaseUrl();
if("pdf".equalsIgnoreCase(tifPreviewType)){
if ("pdf".equalsIgnoreCase(tifPreviewType)) {
// 以PDF模式预览的过程
File filePdf = new File(fileDir + inputFileNamePrefix + ".pdf");
// 如果本地不存在对应的pdf则调用转换过程。否则直接用现有的pdf文件
if(!filePdf.exists()){
if (!filePdf.exists()) {
filePdf = ConvertPicUtil.convertTif2Pdf(strLocalTif, fileDir + inputFileNamePrefix + ".pdf");
}
// 如果pdf已经存在则将url路径加入到对象中返回给页面
if(filePdf.exists()){
assert filePdf != null;
if (filePdf.exists()) {
String pdfUrl = baseUrl + inputFileNamePrefix + ".pdf";
model.addAttribute("pdfUrl", pdfUrl);
return PDF_FILE_PREVIEW_PAGE;
}
}else{
} else {
// 以JPG模式预览的过程
String strJpgFilePathName = fileDir + inputFileNamePrefix + ".jpg";
// 将tif转换为jpg返回转换后的文件路径、文件名的list
@@ -92,7 +98,7 @@ public class TiffFilePreviewImpl implements FilePreview {
// 将返回页面的图片url的list对象
List<String> listImageUrls = new ArrayList<>();
// 循环拼装url的list对象
for(String strJpg : listPic2Jpg){
for (String strJpg : listPic2Jpg) {
listImageUrls.add(baseUrl + strJpg);
}
@@ -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,17 +73,17 @@ 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 = "";
if(intTifCount == 1){
String strJpg;
if (intTifCount == 1) {
strJpg = strJpgPath + "/" + strFilePrefix + ".jpg";
strJpgUrl = strFilePrefix + ".jpg";
}else{
} else {
strJpg = strJpgPath + "/" + i + ".jpg";
strJpgUrl = strFilePrefix + "/" + i + ".jpg";
}
@@ -90,7 +91,7 @@ public class ConvertPicUtil {
File fileJpg = new File(strJpg);
// 如果文件不存在,则生成
if(!fileJpg.exists()){
if (!fileJpg.exists()) {
RenderedImage renderedImage = imageDecoder.decodeAsRenderedImage(i);
ParameterBlock pb = new ParameterBlock();
pb.addSource(renderedImage);
@@ -102,7 +103,7 @@ public class ConvertPicUtil {
renderedOp.dispose();
logger.info("每页分别保存至: " + fileJpg.getCanonicalPath());
}else{
} else {
logger.info("JPG文件已存在 " + fileJpg.getCanonicalPath());
}
@@ -118,21 +119,19 @@ public class ConvertPicUtil {
try {
fileSeekStream.close();
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
fileSeekStream = null;
}
}
}
/**
* 将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 {
@@ -198,16 +192,16 @@ public class ConvertPicUtil {
Image image;
File filePDF;
if(intPages == 1){
if (intPages == 1) {
String strJpg = strTifFile.substring(0, strTifFile.lastIndexOf(".")) + ".jpg";
File fileJpg = new File(strJpg);
List<String> listPic2Jpg = convertTif2Jpg(strTifFile, strJpg);
if(listPic2Jpg != null && fileJpg.exists()){
filePDF = convertJpg2Pdf(strJpg, strPdfFile);
if (listPic2Jpg != null && fileJpg.exists()) {
convertJpg2Pdf(strJpg, strPdfFile);
}
}else{
} else {
for (int i = 1; i <= intPages; i++) {
image = TiffImage.getTiffImage(rafa, i);
// 设置页面宽高与图片一致
@@ -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

@@ -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;
@@ -4641,4 +4641,4 @@ class Encoding {
nicename[OTHER] = "OTHER";
}
}
}

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

@@ -1,12 +1,12 @@
package cn.keking.utils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.poi.EncryptedDocumentException;
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工具类
@@ -16,6 +16,8 @@ import java.io.FileInputStream;
*/
public class OfficeUtils {
private static final String POI_INVALID_PASSWORD_MSG = "Invalid password specified";
/**
* 判断officeword,excel,ppt文件是否受密码保护
*
@@ -25,17 +27,18 @@ public class OfficeUtils {
public static boolean isPwdProtected(String path) {
try {
ExtractorFactory.createExtractor(new FileInputStream(path));
} catch (EncryptedDocumentException e) {
return true;
} catch (IOException e) {
if (POI_INVALID_PASSWORD_MSG.equals(e.getMessage())) {
return true;
}
} catch (Exception e) {
Throwable[] throwables = ExceptionUtils.getThrowables(e);
for (Throwable throwable : throwables) {
if (throwable instanceof EncryptedDocumentException) {
Throwable[] throwableArray = ExceptionUtils.getThrowables(e);
for (Throwable throwable : throwableArray) {
if (throwable instanceof IOException && POI_INVALID_PASSWORD_MSG.equals(throwable.getMessage())) {
return true;
}
}
}
return false;
}
@@ -55,7 +58,6 @@ public class OfficeUtils {
} finally {
Biff8EncryptionKey.setCurrentUserPassword(null);
}
return true;
}

View File

@@ -8,7 +8,9 @@ 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;
@@ -156,22 +158,56 @@ public class WebUtils {
String currentUrl = request.getParameter("currentUrl");
String urlPath = request.getParameter("urlPath");
if (StringUtils.isNotBlank(url)) {
return new String(Base64Utils.decodeFromString(url), StandardCharsets.UTF_8);
return decodeUrl(url);
}
if (StringUtils.isNotBlank(currentUrl)) {
return new String(Base64Utils.decodeFromString(currentUrl), StandardCharsets.UTF_8);
return decodeUrl(currentUrl);
}
if (StringUtils.isNotBlank(urlPath)) {
return new String(Base64Utils.decodeFromString(urlPath), StandardCharsets.UTF_8);
return decodeUrl(urlPath);
}
if (StringUtils.isNotBlank(urls)) {
urls = new String(Base64Utils.decodeFromString(urls), StandardCharsets.UTF_8);
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

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
@@ -51,42 +61,55 @@ public class FileController {
int winSep = fileName.lastIndexOf('\\');
// Cut off at latest possible point
int pos = (Math.max(winSep, unixSep));
if (pos != -1) {
if (pos != -1) {
fileName = fileName.substring(pos + 1);
}
// 判断是否存在同名文件
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.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

@@ -9,24 +9,22 @@ import cn.keking.service.impl.OtherFilePreviewImpl;
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.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.IOException;
import java.io.UnsupportedEncodingException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
@@ -53,11 +51,15 @@ 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);
@@ -69,24 +71,26 @@ 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);
}
logger.info("预览文件url{}urls{}", fileUrls, urls);
// 抽取文件并返回文件列表
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));
@@ -104,26 +108,71 @@ public class OnlinePreviewController {
* @param urlPath url
* @param response response
*/
@RequestMapping(value = "/getCorsFile", method = RequestMethod.GET)
public void getCorsFile(String urlPath, HttpServletResponse response) {
try {
urlPath = new String(Base64.decodeBase64(urlPath), StandardCharsets.UTF_8);
} catch (Exception ex) {
logger.error(String.format(BASE64_DECODE_ERROR_MSG, urlPath, ex));
@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;
}
if (urlPath == null || urlPath.toLowerCase().startsWith("file:") || urlPath.toLowerCase().startsWith("file%3") || !urlPath.toLowerCase().startsWith("http")) {
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);
try {
URL url = WebUtils.normalizedURL(urlPath);
byte[] bytes = NetUtil.downloadBytes(url.toString());
IOUtils.write(bytes, response.getOutputStream());
} catch (IOException | GalimatiasParseException e) {
logger.error("下载跨域pdf文件异常url{}", urlPath, e);
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("读取跨域文件异常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);
}
}
}
@@ -132,12 +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";
}
}

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.*;
@@ -18,7 +19,7 @@ public class BaseUrlFilter implements Filter {
public static String getBaseUrl() {
String baseUrl;
try {
baseUrl = (String) RequestContextHolder.currentRequestAttributes().getAttribute("baseUrl",0);
baseUrl = (String) RequestContextHolder.currentRequestAttributes().getAttribute("baseUrl", 0);
} catch (Exception e) {
baseUrl = BASE_URL;
}
@@ -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);

View File

@@ -0,0 +1,30 @@
package cn.keking.web.filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Configuration
public class SecurityFilterProxy extends OncePerRequestFilter {
private String NOT_ALLOW_METHODS = "TRACE";
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
if((","+NOT_ALLOW_METHODS+",").indexOf(","+request.getMethod().toLowerCase()+",") > -1) {
response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
response.setHeader("Content-Type", "text/html; charset=iso-8859-1");
response.getWriter().println("Method Not Allowed");
return;
}
super.doFilter(request, response, filterChain);
}
}

View File

@@ -2,16 +2,16 @@ package cn.keking.web.filter;
import cn.keking.config.ConfigConstants;
import cn.keking.utils.WebUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.Base64Utils;
import org.springframework.util.FileCopyUtils;
import javax.servlet.*;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.FileCopyUtils;
/**
* @author chenjh

View File

@@ -0,0 +1,14 @@
_ _ ______ _ _ __ __ _
| | | | | ____| (_) | | \ \ / / (_)
| | __ | | __ | |__ _ | | ___ \ \ / / _ ___ __ __
| |/ / | |/ / | __| | | | | / _ \ \ \/ / | | / _ \ \ \ /\ / /
| < | < | | | | | | | __/ \ / | | | __/ \ V V /
|_|\_\ |_|\_\ |_| |_| |_| \___| \/ |_| \___| \_/\_/
=> Spring Boot :: ${spring-boot.version}
=> kkFileView :: 4.1.0
=> Home site :: https://kkfileview.keking.cn
=> Github :: https://github.com/kekingcn/kkFileView
=> Gitee :: https://gitee.com/kekingcn/file-online-preview
=> kk opensource community :: https://t.zsxq.com/09ZHSXbsQ

View File

@@ -1,6 +1,6 @@
/*!
* Bootstrap v3.3.7 (http://getbootstrap.com)
* Copyright 2011-2016 Twitter, Inc.
* Bootstrap v3.4.1 (https://getbootstrap.com/)
* Copyright 2011-2019 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*/
.btn-default,
@@ -9,9 +9,9 @@
.btn-info,
.btn-warning,
.btn-danger {
text-shadow: 0 -1px 0 rgba(0, 0, 0, .2);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
}
.btn-default:active,
.btn-primary:active,
@@ -25,8 +25,8 @@
.btn-info.active,
.btn-warning.active,
.btn-danger.active {
-webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
-webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
}
.btn-default.disabled,
.btn-primary.disabled,
@@ -47,7 +47,7 @@ fieldset[disabled] .btn-info,
fieldset[disabled] .btn-warning,
fieldset[disabled] .btn-danger {
-webkit-box-shadow: none;
box-shadow: none;
box-shadow: none;
}
.btn-default .badge,
.btn-primary .badge,
@@ -62,15 +62,15 @@ fieldset[disabled] .btn-danger {
background-image: none;
}
.btn-default {
text-shadow: 0 1px 0 #fff;
background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);
background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);
background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0));
background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);
background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #dbdbdb;
text-shadow: 0 1px 0 #fff;
border-color: #ccc;
}
.btn-default:hover,
@@ -106,9 +106,9 @@ fieldset[disabled] .btn-default.active {
}
.btn-primary {
background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88));
background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);
background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
@@ -147,9 +147,9 @@ fieldset[disabled] .btn-primary.active {
}
.btn-success {
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);
background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641));
background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
@@ -188,9 +188,9 @@ fieldset[disabled] .btn-success.active {
}
.btn-info {
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2));
background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
@@ -229,9 +229,9 @@ fieldset[disabled] .btn-info.active {
}
.btn-warning {
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316));
background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
@@ -270,9 +270,9 @@ fieldset[disabled] .btn-warning.active {
}
.btn-danger {
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a));
background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
@@ -311,81 +311,81 @@ fieldset[disabled] .btn-danger.active {
}
.thumbnail,
.img-thumbnail {
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
}
.dropdown-menu > li > a:hover,
.dropdown-menu > li > a:focus {
background-color: #e8e8e8;
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
background-repeat: repeat-x;
background-color: #e8e8e8;
}
.dropdown-menu > .active > a,
.dropdown-menu > .active > a:hover,
.dropdown-menu > .active > a:focus {
background-color: #2e6da4;
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
background-repeat: repeat-x;
background-color: #2e6da4;
}
.navbar-default {
background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%);
background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8));
background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%);
background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);
background-image: -o-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#ffffff), to(#f8f8f8));
background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
}
.navbar-default .navbar-nav > .open > a,
.navbar-default .navbar-nav > .active > a {
background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2));
background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);
background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);
background-repeat: repeat-x;
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);
}
.navbar-brand,
.navbar-nav > li > a {
text-shadow: 0 1px 0 rgba(255, 255, 255, .25);
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);
}
.navbar-inverse {
background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);
background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);
background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222));
background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);
background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
border-radius: 4px;
}
.navbar-inverse .navbar-nav > .open > a,
.navbar-inverse .navbar-nav > .active > a {
background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);
background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);
background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f));
background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);
background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);
background-repeat: repeat-x;
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);
box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);
}
.navbar-inverse .navbar-brand,
.navbar-inverse .navbar-nav > li > a {
text-shadow: 0 -1px 0 rgba(0, 0, 0, .25);
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
}
.navbar-static-top,
.navbar-fixed-top,
@@ -398,120 +398,120 @@ fieldset[disabled] .btn-danger.active {
.navbar .navbar-nav .open .dropdown-menu > .active > a:focus {
color: #fff;
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
background-repeat: repeat-x;
}
}
.alert {
text-shadow: 0 1px 0 rgba(255, 255, 255, .2);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
}
.alert-success {
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc));
background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
background-repeat: repeat-x;
border-color: #b2dba1;
}
.alert-info {
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0));
background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
background-repeat: repeat-x;
border-color: #9acfea;
}
.alert-warning {
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0));
background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
background-repeat: repeat-x;
border-color: #f5e79e;
}
.alert-danger {
background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3));
background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
background-repeat: repeat-x;
border-color: #dca7a7;
}
.progress {
background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5));
background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar {
background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090));
background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);
background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar-success {
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);
background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44));
background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar-info {
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5));
background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar-warning {
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f));
background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar-danger {
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);
background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c));
background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar-striped {
background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
}
.list-group {
border-radius: 4px;
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
}
.list-group-item.active,
.list-group-item.active:hover,
.list-group-item.active:focus {
text-shadow: 0 -1px 0 #286090;
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a));
background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);
background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);
background-repeat: repeat-x;
border-color: #2b669a;
@@ -522,66 +522,66 @@ fieldset[disabled] .btn-danger.active {
text-shadow: none;
}
.panel {
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}
.panel-default > .panel-heading {
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
background-repeat: repeat-x;
}
.panel-primary > .panel-heading {
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
background-repeat: repeat-x;
}
.panel-success > .panel-heading {
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6));
background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
background-repeat: repeat-x;
}
.panel-info > .panel-heading {
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3));
background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
background-repeat: repeat-x;
}
.panel-warning > .panel-heading {
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc));
background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
background-repeat: repeat-x;
}
.panel-danger > .panel-heading {
background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc));
background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
background-repeat: repeat-x;
}
.well {
background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5));
background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
background-repeat: repeat-x;
border-color: #dcdcdc;
-webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
-webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
}
/*# sourceMappingURL=bootstrap-theme.css.map */
/*# sourceMappingURL=bootstrap-theme.css.map */

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

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