Compare commits

...

45 Commits

Author SHA1 Message Date
陈精华
b1fdbd26a3 新功能点:全部能识别的纯文本直接预览,不用再转跳下载(.md、.java、.py等浏览器不认识的后缀名) 2019-10-25 15:16:25 +08:00
陈精华
fa7241bd4e 新功能点:所有配置项支持从环境变量里读取,方便Docker镜像部署 2019-10-25 15:16:25 +08:00
陈精华
8fdf462c6c 新功能点:缓存清理时间cron表达式支持自定义 link #I1147X 2019-10-25 15:16:25 +08:00
陈精华
f7c7411bcf fixup! 优化:目录调整,符合maven规范;maven编译指定.sh脚本换行符为unix换行 2019-10-25 15:16:25 +08:00
陈精华
845cb2e657 修复:参数包含特殊字符时url解码失败 2019-10-25 15:16:25 +08:00
陈精华
a4bfde68bd 优化:目录调整,符合maven规范;maven编译指定.sh脚本换行符为unix换行 2019-10-25 15:16:25 +08:00
陈精华
19d1ba6cf9 优化:(内部)移除为pdf文档提供base64缩略图 2019-10-25 15:16:25 +08:00
陈精华
1060bdd00f 新功能点:支持base url配置(主要用于nginx反向代理等) 2019-10-17 11:36:43 +08:00
陈精华
8c2fb2bdee 优化:默认启用缓存 2019-10-17 11:36:43 +08:00
陈精华
0fe75387eb 优化:启动脚本加入官网链接,点star推广等文案 close #I1148F 2019-09-16 11:49:49 +08:00
陈精华
fbea49e54f 优化:加入查看日志脚本 2019-09-16 11:49:49 +08:00
陈精华
41a72798d9 优化:去除可能导致文件不更新的缓存 2019-09-16 11:49:49 +08:00
陈精华
03cc185085 修复:压缩包中文件名有空格异常 2019-09-16 11:49:49 +08:00
陈精华
bfbd8ee25e 新功能点:(内部)为pdf文档提供base64缩略图 2019-09-10 18:24:06 +08:00
陈精华
f3f36169ff 优化:压缩文件名支持有特殊字符 2019-09-10 18:24:06 +08:00
陈精华
2df88544d3 修复:macOS下office组件默认路径错误 2019-09-10 18:24:06 +08:00
陈精华
6b744d77c7 修复:RocksDB缓存实现压缩包图片url缓存失效 2019-09-10 18:24:06 +08:00
doras
ba57dedebb "加入是否启用缓存配置项"后,excel转成的html文件不再转换编码,修复因此出现的乱码问题 2019-08-26 11:17:37 +08:00
陈精华
affd5b3057 图片和pdf预览模式切换按钮大小调整 2019-08-23 18:18:37 +08:00
陈精华
30c3128995 修复压缩文件中文fileKey未编码 link #I111PD 2019-08-23 18:18:37 +08:00
陈精华
b003a05775 加入是否启用缓存配置项 2019-08-23 18:18:37 +08:00
陈精华
98ec3d7dab 首页预览打开新页面 2019-08-23 18:18:37 +08:00
陈精华
69e23dbb99 shutdown脚本更新 2019-08-23 18:18:37 +08:00
陈精华
47bda1023a 修复Chrome76+删除弹出新窗口 2019-08-23 18:18:37 +08:00
陈精华
fd538a74af 中文语言环境 2019-08-23 18:18:37 +08:00
陈精华
300d213a7a cdn资源不指定http/https 2019-08-23 18:18:37 +08:00
陈精华
4c0a70f300 2.2.0迭代 2019-08-23 18:18:37 +08:00
陈精华
8798d344b6 2.1.2版 2019-07-30 16:31:53 +08:00
陈精华
63e62ab57b pdf.js使用里面一个bug 2019-07-30 16:31:53 +08:00
陈精华
9a027674ac 演示首页兼容IE 2019-07-30 16:31:53 +08:00
1045485954@qq.com
e4407467dd IE兼容性问题,目前已兼容到IE9 2019-07-17 09:03:32 +08:00
陈精华
551eeb0390 2.1.1版 2019-07-09 10:46:21 +08:00
陈精华
11d6ad1ed3 修复文件下载流URL参数中包含中文URL编码不正确导致HTTP-400异常 2019-07-09 10:46:21 +08:00
陈精华
e57db6925c 修复config.js 404问题 2019-07-09 10:46:21 +08:00
陈精华
87096364d8 首页示例修改、首页更新记录 2019-07-09 10:46:21 +08:00
陈精华
ad8027a7d0 2.1.1迭代 2019-07-09 10:46:21 +08:00
陈精华
9786fa8275 2.1.0版 2019-06-19 15:24:24 +08:00
陈精华
37762cf034 支持FTP文件地址作为预览源url 2019-06-19 15:24:24 +08:00
陈精华
a78f1e5f8e Docker构建 2019-06-19 15:24:24 +08:00
陈精华
440b8030e0 新增Docker构建 2019-06-19 15:24:24 +08:00
陈精华
fb7cdfbef7 支持http/https文件流作为预览源url 2019-06-19 15:24:24 +08:00
陈精华
cf1ee9c631 支持自动清理预览文件及缓存 2019-06-19 15:24:24 +08:00
陈精华
13123f8f9d addTask转码优化 2019-06-19 15:24:24 +08:00
陈精华
189bc3965d 2.1.0迭代 2019-06-19 15:24:24 +08:00
kl
0aa7444dba Update pom.xml 2019-05-30 09:08:08 +08:00
49 changed files with 747 additions and 306 deletions

2
.gitignore vendored
View File

@@ -38,3 +38,5 @@ nbdist/
/.temfile /.temfile
.temfile .temfile
convertedFile/ convertedFile/
jodconverter-web/src/main/cache/
jodconverter-web/src/main/file/

34
Dockerfile Normal file
View File

@@ -0,0 +1,34 @@
FROM centos:centos7.6.1810
MAINTAINER chenjh "842761733@qq.com"
ADD jodconverter-web/target/kkFileView-*.tar.gz /opt/
COPY fonts/* /usr/share/fonts/chienes/
RUN yum install -y kde-l10n-Chinese &&\
yum install -y glibc-common &&\
yum install -y fontconfig &&\
yum install -y mkfontscale &&\
localedef -c -f UTF-8 -i zh_CN zh_CN.utf8 &&\
echo "LANG=zh_CN.UTF-8" > /etc/locale.conf &&\
source /etc/locale.conf &&\
export LANG=zh_CN.UTF-8 &&\
LANG="zh_CN.UTF-8" &&\
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime &&\
yum install -y java-1.8.0-openjdk.x86_64 &&\
yum install -y wget &&\
yum install -y libXext.x86_64 &&\
yum groupinstall -y "X Window System" &&\
cd /tmp &&\
wget https://iweb.dl.sourceforge.net/project/openofficeorg.mirror/4.1.6/binaries/zh-CN/Apache_OpenOffice_4.1.6_Linux_x86-64_install-rpm_zh-CN.tar.gz -cO openoffice_rpm.tar.gz &&\
tar zxf /tmp/openoffice_rpm.tar.gz &&\
cd /tmp/zh-CN/RPMS &&\
rpm -Uvih *.rpm &&\
rpm -Uvih desktop-integration/openoffice4.1.6-redhat-menus-4.1.6-9790.noarch.rpm &&\
rm -f /tmp/openoffice_rpm.tar.gz &&\
rm -rf /tmp/zh-CN &&\
cd /usr/share/fonts/chienes &&\
mkfontscale &&\
mkfontdir &&\
fc-cache -fv
ENV LANG zh_CN.UTF-8
ENV LC_ALL zh_CN.UTF-8
ENV KKFILEVIEW_BIN_FOLDER /opt/kkFileView-2.2.0-SNAPSHOT/bin
ENTRYPOINT ["java","-Dfile.encoding=UTF-8","-Dsun.java2d.cmm=sun.java2d.cmm.kcms.KcmsServiceProvider","-Dspring.config.location=/opt/kkFileView-2.2.0-SNAPSHOT/config/application.properties","-jar","/opt/kkFileView-2.2.0-SNAPSHOT/bin/kkFileView-2.2.0-SNAPSHOT.jar"]

View File

@@ -58,26 +58,22 @@ Considering space issues, the pictures of other types of documents will not be s
- Jodconverter - Jodconverter
> Dependencies > Dependencies
- Redis(Optional, Unnecessary by default) - Redis(Optional, Unnecessary by default)
- OpenOffice or LibreOffice - OpenOffice or LibreOffice(Integrated on Windows, will be installed automatically on Linux, need to be manually installed on Mac OS)
1. First step`git pull https://github.com/kekingcn/file-online-preview.git` 1. First step`git pull https://github.com/kekingcn/file-online-preview.git`
2. Second stepconfigure redis address and OpenOffice directorysuch as 2. Third stepRun the main method of FilePreviewApplication.java.After starting,visit `http://localhost:8012/`.
```
##The folder for files which are uploaded to the server(Because of running as jar)
file.dir = C:\\Users\\yudian\\Desktop\\dev\\
## openoffice configuration
office.home = C:\\Program Files (x86)\\OpenOffice 4
```
'file.dir' is the real storage address of the converted files, please end with '/'.
3. Third stepRun the main method of FilePreviewApplication.java.After starting,visit `http://localhost:8012/`.
If everything is ok,you will see the picture below. If everything is ok,you will see the picture below.
![输入图片说明](https://gitee.com/uploads/images/2017/1213/100221_ea15202e_492218.png "屏幕截图.png") ![输入图片说明](https://gitee.com/uploads/images/2017/1213/100221_ea15202e_492218.png "屏幕截图.png")
### Changelog ### Changelog
> June 18th 2019
1. Support automatic cleaning of cache and preview files
2. Support http/https stream url file preview
3. Support FTP url file preview
4. Add Docker build
> April 8th 2019 > April 8th 2019
1. Cache and queue implementations abstract, providing JDK and REDIS implementations (REDIS becomes optional dependencies) 1. Cache and queue implementations abstract, providing JDK and REDIS implementations (REDIS becomes optional dependencies)
2. Provides zip and tar.gz packages, and provides a one-click startup script 2. Provides zip and tar.gz packages, and provides a one-click startup script

View File

@@ -52,26 +52,22 @@ QQ群号613025121
- jodconverter - jodconverter
> 依赖外部环境 > 依赖外部环境
- redis (可选,默认不用) - redis (可选,默认不用)
- OpenOffice或者LibreOffice - OpenOffice或者LibreOffice(Windows下已内置Linux会自动安装Mac OS下需要手动安装)
1. 第一步pull项目https://github.com/kekingcn/file-online-preview.git 1. 第一步pull项目https://github.com/kekingcn/file-online-preview.git
2. 第二步:配置OpenOffice目录 3. 第二步:运行FilePreviewApplication的main方法服务启动后访问http://localhost:8012/
```
##资源映射路径(因为jar方式运行的原因)
file.dir = C:\\Users\\yudian\\Desktop\\dev\\
## openoffice相关配置
office.home = C:\\Program Files (x86)\\OpenOffice 4
```
file.dir为转换文件实际存储地址注意要以/结尾
3. 第三步运行FilePreviewApplication的main方法服务启动后访问http://localhost:8012/
会看到如下界面,代表服务启动成功 会看到如下界面,代表服务启动成功
![输入图片说明](https://gitee.com/uploads/images/2017/1213/100221_ea15202e_492218.png "屏幕截图.png") ![输入图片说明](https://gitee.com/uploads/images/2017/1213/100221_ea15202e_492218.png "屏幕截图.png")
### 历史更新记录 ### 历史更新记录
> 2019年06月18日
1. 支持自动清理缓存及预览文件
2. 支持http/https下载流url文件预览
3. 支持FTP url文件预览
4. 加入Docker构建
> 2019年04月08日 > 2019年04月08日
1. 缓存及队列实现抽象提供JDK和REDIS两种实现(REDIS成为可选依赖) 1. 缓存及队列实现抽象提供JDK和REDIS两种实现(REDIS成为可选依赖)
2. 打包方式提供zip和tar.gz包并提供一键启动脚本 2. 打包方式提供zip和tar.gz包并提供一键启动脚本

0
fonts/.gitkeep Normal file
View File

View File

@@ -15,6 +15,7 @@ package org.artofsolving.jodconverter.office;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileReader; import java.io.FileReader;
import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
@@ -26,6 +27,8 @@ import com.sun.star.uno.UnoRuntime;
public class OfficeUtils { public class OfficeUtils {
public static final String SERVICE_DESKTOP = "com.sun.star.frame.Desktop"; public static final String SERVICE_DESKTOP = "com.sun.star.frame.Desktop";
public static final String OFFICE_HOME_KEY = "office.home";
public static final String DEFAULT_OFFICE_HOME_VALUE = "default";
private OfficeUtils() { private OfficeUtils() {
throw new AssertionError("utility class must not be instantiated"); throw new AssertionError("utility class must not be instantiated");
@@ -69,9 +72,11 @@ public class OfficeUtils {
try { try {
BufferedReader bufferedReader = new BufferedReader(new FileReader(customizedConfigPath)); BufferedReader bufferedReader = new BufferedReader(new FileReader(customizedConfigPath));
properties.load(bufferedReader); properties.load(bufferedReader);
restorePropertiesFromEnvFormat(properties);
} catch (Exception e) {} } catch (Exception e) {}
if (properties.getProperty("office.home") != null) { String officeHome = properties.getProperty(OFFICE_HOME_KEY);
return new File(properties.getProperty("office.home")); if (officeHome != null && !DEFAULT_OFFICE_HOME_VALUE.equals(officeHome)) {
return new File(officeHome);
} }
if (PlatformUtils.isWindows()) { if (PlatformUtils.isWindows()) {
// %ProgramFiles(x86)% on 64-bit machines; %ProgramFiles% on 32-bit ones // %ProgramFiles(x86)% on 64-bit machines; %ProgramFiles% on 32-bit ones
@@ -116,7 +121,7 @@ public class OfficeUtils {
public static File getOfficeExecutable(File officeHome) { public static File getOfficeExecutable(File officeHome) {
if (PlatformUtils.isMac()) { if (PlatformUtils.isMac()) {
return new File(officeHome, "MacOS/soffice.bin"); return new File(officeHome, "MacOS/soffice");
} else { } else {
return new File(officeHome, "program/soffice.bin"); return new File(officeHome, "program/soffice.bin");
} }
@@ -143,8 +148,36 @@ public class OfficeUtils {
public static String getCustomizedConfigPath() { public static String getCustomizedConfigPath() {
String homePath = OfficeUtils.getHomePath(); String homePath = OfficeUtils.getHomePath();
String separator = java.io.File.separator; String separator = java.io.File.separator;
String configFilePath = homePath + separator + "conf" + separator + "application.properties"; String configFilePath = homePath + separator + "config" + separator + "application.properties";
return configFilePath; return configFilePath;
} }
/**
* SpringBoot application.properties 支持从环境变量获取值
* @param properties
*/
public synchronized static void restorePropertiesFromEnvFormat(Properties properties) {
Iterator<Map.Entry<Object, Object>> iterator = properties.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<Object, Object> entry = iterator.next();
String key = entry.getKey().toString();
String value = entry.getValue().toString();
if (value.trim().startsWith("${") && value.trim().endsWith("}")) {
int beginIndex = value.indexOf(":");
if (beginIndex < 0) {
beginIndex = value.length() - 1;
}
int endIndex = value.length() - 1;
String envKey = value.substring(2, beginIndex);
String envValue = System.getenv(envKey);
if (envValue == null || "".equals(envValue.trim())) {
value = value.substring(beginIndex + 1, endIndex);
} else {
value = envValue;
}
properties.setProperty(key, value);
}
}
}
} }

View File

@@ -12,7 +12,7 @@
<groupId>cn.keking</groupId> <groupId>cn.keking</groupId>
<artifactId>kkFileView</artifactId> <artifactId>kkFileView</artifactId>
<version>2.0.2</version> <version>2.2.0-SNAPSHOT</version>
<properties> <properties>
@@ -147,10 +147,16 @@
<artifactId>commons-cli</artifactId> <artifactId>commons-cli</artifactId>
<version>1.2</version> <version>1.2</version>
</dependency> </dependency>
<!-- FTP -->
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.6</version>
</dependency>
<dependency> <dependency>
<groupId>com.thoughtworks.xstream</groupId> <groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId> <artifactId>xstream</artifactId>
<version>1.3.1</version> <version>1.4.6</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.google.guava</groupId> <groupId>com.google.guava</groupId>
@@ -188,7 +194,7 @@
<filtering>true</filtering> <filtering>true</filtering>
</resource> </resource>
<resource> <resource>
<directory>src/main/conf</directory> <directory>src/main/config</directory>
<excludes> <excludes>
<exclude>${build.exclude.resource}</exclude> <exclude>${build.exclude.resource}</exclude>
</excludes> </excludes>
@@ -204,7 +210,7 @@
<configuration> <configuration>
<appendAssemblyId>false</appendAssemblyId> <appendAssemblyId>false</appendAssemblyId>
<descriptors> <descriptors>
<descriptor>src/main/resources/assembly.xml</descriptor> <descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors> </descriptors>
</configuration> </configuration>
<executions> <executions>

View File

@@ -11,18 +11,24 @@
<includeBaseDirectory>true</includeBaseDirectory> <includeBaseDirectory>true</includeBaseDirectory>
<fileSets> <fileSets>
<fileSet> <fileSet>
<directory>src/main/conf</directory> <directory>src/main/bin</directory>
<outputDirectory>${file.separator}conf</outputDirectory> <outputDirectory>${file.separator}bin</outputDirectory>
<includes>
<include>*.sh</include>
</includes>
<fileMode>755</fileMode>
<lineEnding>unix</lineEnding>
</fileSet> </fileSet>
<fileSet> <fileSet>
<directory>src/main/bin</directory> <directory>src/main/bin</directory>
<outputDirectory>${file.separator}bin</outputDirectory> <outputDirectory>${file.separator}bin</outputDirectory>
<fileMode>755</fileMode> <includes>
<include>*.bat</include>
</includes>
</fileSet> </fileSet>
<fileSet> <fileSet>
<directory>src/main/script</directory> <directory>src/main/config</directory>
<outputDirectory>${file.separator}script</outputDirectory> <outputDirectory>${file.separator}config</outputDirectory>
<fileMode>755</fileMode>
</fileSet> </fileSet>
<fileSet> <fileSet>
<directory>src/main/log</directory> <directory>src/main/log</directory>

View File

@@ -0,0 +1,2 @@
#!/bin/bash
tail -fn 300 ../log/kkFileView.log

View File

@@ -1,2 +1,2 @@
#!/bin/bash #!/bin/bash
kill 15 `ps -ef|grep kkFileView|awk '{print $2}'` kill -15 `ps -ef|grep kkFileView|awk 'NR==1{print $2}'`

View File

@@ -3,5 +3,7 @@ set "KKFILEVIEW_BIN_FOLDER=%cd%"
cd "%KKFILEVIEW_BIN_FOLDER%" cd "%KKFILEVIEW_BIN_FOLDER%"
echo Using KKFILEVIEW_BIN_FOLDER %KKFILEVIEW_BIN_FOLDER% echo Using KKFILEVIEW_BIN_FOLDER %KKFILEVIEW_BIN_FOLDER%
echo Starting kkFileView... echo Starting kkFileView...
echo Please check log file for more information echo Please check log file in ../log/kkFileView.log for more information
java -Dsun.java2d.cmm=sun.java2d.cmm.kcms.KcmsServiceProvider -Dspring.config.location=..\conf\application.properties -jar kkFileView-2.0.2.jar -> ..\log\kkFileView.log echo You can get help in our official homesite: https://kkFileView.keking.cn
echo If this project is helpful to you, please star it on https://gitee.com/kekingcn/file-online-preview/stargazers
java -Dsun.java2d.cmm=sun.java2d.cmm.kcms.KcmsServiceProvider -Dspring.config.location=..\config\application.properties -jar kkFileView-2.2.0-SNAPSHOT.jar -> ..\log\kkFileView.log

View File

@@ -6,7 +6,7 @@ KKFILEVIEW_BIN_FOLDER=$(cd "$(dirname "$0")";pwd)
export KKFILEVIEW_BIN_FOLDER=$KKFILEVIEW_BIN_FOLDER export KKFILEVIEW_BIN_FOLDER=$KKFILEVIEW_BIN_FOLDER
cd $KKFILEVIEW_BIN_FOLDER cd $KKFILEVIEW_BIN_FOLDER
echo "Using KKFILEVIEW_BIN_FOLDER $KKFILEVIEW_BIN_FOLDER" echo "Using KKFILEVIEW_BIN_FOLDER $KKFILEVIEW_BIN_FOLDER"
grep 'office\.home' ../conf/application.properties | grep '!^#' grep 'office\.home' ../config/application.properties | grep '!^#'
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
echo "Using customized office.home" echo "Using customized office.home"
else else
@@ -20,11 +20,13 @@ else
done done
if [ ! -n "${FLAG}" ]; then if [ ! -n "${FLAG}" ]; then
echo "Installing OpenOffice" echo "Installing OpenOffice"
sh ../script/install.sh sh ./install.sh
else else
echo "Detected office component has been installed in $OFFICE_HOME" echo "Detected office component has been installed in $OFFICE_HOME"
fi fi
fi fi
echo "Starting kkFileView..." echo "Starting kkFileView..."
echo "Please check log file for more information" echo "Please execute ./showlog.sh to check log for more information"
nohup java -Dsun.java2d.cmm=sun.java2d.cmm.kcms.KcmsServiceProvider -Dspring.config.location=../conf/application.properties -jar kkFileView-2.0.2.jar > ../log/kkFileView.log 2>&1 & echo "You can get help in our official homesite: https://kkFileView.keking.cn"
echo "If this project is helpful to you, please star it on https://gitee.com/kekingcn/file-online-preview/stargazers"
nohup java -Dfile.encoding=UTF-8 -Dsun.java2d.cmm=sun.java2d.cmm.kcms.KcmsServiceProvider -Dspring.config.location=../config/application.properties -jar kkFileView-2.2.0-SNAPSHOT.jar > ../log/kkFileView.log 2>&1 &

View File

@@ -1,39 +0,0 @@
#######################################不可动态配置,需要重启生效#######################################
server.port = 8012
spring.http.encoding.charset = utf8
## Freemarker 配置
spring.freemarker.template-loader-path = classpath:/web/
spring.freemarker.cache = false
spring.freemarker.charset = UTF-8
spring.freemarker.check-template-location = true
spring.freemarker.content-type = text/html
spring.freemarker.expose-request-attributes = true
spring.freemarker.expose-session-attributes = true
spring.freemarker.request-context-attribute = request
spring.freemarker.suffix = .ftl
server.tomcat.uri-encoding = UTF-8
#文件上传限制
spring.http.multipart.max-request-size=100MB
spring.http.multipart.max-file-size=100MB
#文件资源路径默认为打包根路径下的file目录下
#file.dir = D:\\kkFileview\\
#openoffice home路径
#office.home = C:\\Program Files (x86)\\OpenOffice 4
#缓存实现类型不配默认为内嵌RocksDB实现可配置为redis(type = redis)实现需要配置spring.redisson.address等参数和 JDK 内置对象实现type = jdk,
#cache.type = redis
#redis连接
#spring.redisson.address = 192.168.1.204:6379
#spring.redisson.password = xxx
#######################################可在运行时动态配置#######################################
#文本类型,默认如下,可自定义添加
#simText = txt,html,xml,properties,md,java,py,c,cpp,sql
#多媒体类型,默认如下,可自定义添加
#media = mp3,wav,mp4,flv
#文件转换编码,默认根据操作系统获取
#converted.file.charset = GBK
#office类型文档(word ppt)样式,默认为图片(image)可配置为pdf预览时也有按钮切换
#office.preview.type = pdf

View File

@@ -0,0 +1,57 @@
#######################################不可动态配置,需要重启生效#######################################
server.port = ${KK_SERVER_PORT:8012}
spring.http.encoding.charset = utf8
## Freemarker 配置
spring.freemarker.template-loader-path = classpath:/web/
spring.freemarker.cache = false
spring.freemarker.charset = UTF-8
spring.freemarker.check-template-location = true
spring.freemarker.content-type = text/html
spring.freemarker.expose-request-attributes = true
spring.freemarker.expose-session-attributes = true
spring.freemarker.request-context-attribute = request
spring.freemarker.suffix = .ftl
server.tomcat.uri-encoding = UTF-8
#文件上传限制
spring.http.multipart.max-request-size=100MB
spring.http.multipart.max-file-size=100MB
#文件资源路径默认为打包根路径下的file目录下
#file.dir = D:\\kkFileview\\
file.dir = ${KK_FILE_DIR:default}
#openoffice home路径
#office.home = C:\\Program Files (x86)\\OpenOffice 4
office.home = ${KK_OFFICE_HOME:default}
#缓存实现类型不配默认为内嵌RocksDB(type = default)实现可配置为redis(type = redis)实现需要配置spring.redisson.address等参数和 JDK 内置对象实现type = jdk,
cache.type = ${KK_CACHE_TYPE:default}
#redis连接只有当cache.type = redis时才有用
spring.redisson.address = ${KK_SPRING_REDISSON_ADDRESS:127.0.0.1:6379}
spring.redisson.password = ${KK_SPRING_REDISSON_PASSWORD:123456}
#缓存是否自动清理 true 为开启,注释掉或其他值都为关闭
cache.clean.enabled = ${KK_CACHE_CLEAN_ENABLED:true}
#缓存自动清理时间cache.clean.enabled = true时才有用cron表达式基于Quartz cron
cache.clean.cron = ${KK_CACHE_CLEAN_CRON:0 0 3 * * ?}
#######################################可在运行时动态配置#######################################
#提供预览服务的地址默认从请求url读如果使用nginx等反向代理需要手动设置
#base.url = https://file.keking.cn
base.url = ${KK_BASE_URL:default}
#是否启用缓存
cache.enabled = ${KK_CACHE_ENABLED:true}
#文本类型,默认如下,可自定义添加
simText = ${KK_SIMTEXT:txt,html,htm,asp,jsp,xml,json,properties,md,gitignore,,java,py,c,cpp,sql,sh,bat,m,bas,prg,cmd}
#多媒体类型,默认如下,可自定义添加
media = ${KK_MEDIA:mp3,wav,mp4,flv}
#office类型文档(word ppt)样式,默认为图片(image)可配置为pdf预览时也有按钮切换
office.preview.type = ${KK_OFFICE_PREVIEW_TYPE:image}
#预览源为FTP时 FTP用户名可在ftp url后面加参数ftp.username=ftpuser指定不指定默认用配置的
ftp.username = ${KK_FTP_USERNAME:ftpuser}
#预览源为FTP时 FTP密码可在ftp url后面加参数ftp.password=123456指定不指定默认用配置的
ftp.password = ${KK_FTP_PASSWORD:123456}
#预览源为FTP时, FTP连接默认ControlEncoding(根据FTP服务器操作系统选择Linux一般为UTF-8Windows一般为GBK)可在ftp url后面加参数ftp.control.encoding=UTF-8指定不指定默认用配置的
ftp.control.encoding = ${KK_FTP_CONTROL_ENCODING:UTF-8}

View File

@@ -14,11 +14,25 @@ import java.io.File;
@Component @Component
public class ConfigConstants { public class ConfigConstants {
private static Boolean cacheEnabled;
private static String[] simText = {}; private static String[] simText = {};
private static String[] media = {}; private static String[] media = {};
private static String convertedFileCharset;
private static String officePreviewType; private static String officePreviewType;
private static String ftpUsername;
private static String ftpPassword;
private static String ftpControlEncoding;
private static String fileDir = OfficeUtils.getHomePath() + File.separator + "file" + File.separator; private static String fileDir = OfficeUtils.getHomePath() + File.separator + "file" + File.separator;
private static String baseUrl;
public static final String DEFAULT_FILE_DIR_VALUE = "default";
public static Boolean isCacheEnabled() {
return cacheEnabled;
}
public static void setCacheEnabled(Boolean cacheEnabled) {
ConfigConstants.cacheEnabled = cacheEnabled;
}
public static String[] getSimText() { public static String[] getSimText() {
return simText; return simText;
@@ -36,14 +50,6 @@ public class ConfigConstants {
ConfigConstants.media = media; ConfigConstants.media = media;
} }
public static String getConvertedFileCharset() {
return convertedFileCharset;
}
public static void setConvertedFileCharset(String convertedFileCharset) {
ConfigConstants.convertedFileCharset = convertedFileCharset;
}
public static String getOfficePreviewType() { public static String getOfficePreviewType() {
return officePreviewType; return officePreviewType;
} }
@@ -52,13 +58,45 @@ public class ConfigConstants {
ConfigConstants.officePreviewType = officePreviewType; ConfigConstants.officePreviewType = officePreviewType;
} }
public static String getFtpUsername() {
return ftpUsername;
}
public static void setFtpUsername(String ftpUsername) {
ConfigConstants.ftpUsername = ftpUsername;
}
public static String getFtpPassword() {
return ftpPassword;
}
public static String getFtpControlEncoding() {
return ftpControlEncoding;
}
public static void setFtpControlEncoding(String ftpControlEncoding) {
ConfigConstants.ftpControlEncoding = ftpControlEncoding;
}
public static void setFtpPassword(String ftpPassword) {
ConfigConstants.ftpPassword = ftpPassword;
}
public static String getFileDir() { public static String getFileDir() {
return fileDir; return fileDir;
} }
public static String getBaseUrl() {
return baseUrl;
}
public static void setBaseUrl(String baseUrl) {
ConfigConstants.baseUrl = baseUrl;
}
@Value("${file.dir:default}") @Value("${file.dir:default}")
public void setFileDir(String fileDir) { public void setFileDir(String fileDir) {
if (!"default".equals(fileDir)) { if (!DEFAULT_FILE_DIR_VALUE.equals(fileDir.toLowerCase())) {
if (!fileDir.endsWith(File.separator)) { if (!fileDir.endsWith(File.separator)) {
fileDir = fileDir + File.separator; fileDir = fileDir + File.separator;
} }

View File

@@ -22,9 +22,14 @@ public class ConfigRefreshComponent {
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigRefreshComponent.class); private static final Logger LOGGER = LoggerFactory.getLogger(ConfigRefreshComponent.class);
public static final String DEFAULT_TXT_TYPE = "txt,html,xml,properties,md,java,py,c,cpp,sql"; public static final String DEFAULT_CACHE_ENABLED = "true";
public static final String DEFAULT_TXT_TYPE = "txt,html,htm,asp,jsp,xml,json,properties,md,gitignore,,java,py,c,cpp,sql,sh,bat,m,bas,prg,cmd";
public static final String DEFAULT_MEDIA_TYPE = "mp3,wav,mp4,flv"; public static final String DEFAULT_MEDIA_TYPE = "mp3,wav,mp4,flv";
public static final String DEFAULT_FTP_USERNAME = null;
public static final String DEFAULT_FTP_PASSWORD = null;
public static final String DEFAULT_FTP_CONTROL_ENCODING = "UTF-8";
public static final String DEFAULT_BASE_URL = "default";
@PostConstruct @PostConstruct
void refresh() { void refresh() {
@@ -37,34 +42,46 @@ public class ConfigRefreshComponent {
public void run() { public void run() {
try { try {
Properties properties = new Properties(); Properties properties = new Properties();
Properties sysProperties = System.getProperties();
String text; String text;
String media; String media;
String convertedFileCharset = sysProperties.getProperty("sun.jnu.encoding"); Boolean cacheEnabled;
String[] textArray; String[] textArray;
String[] mediaArray; String[] mediaArray;
String officePreviewType; String officePreviewType;
String ftpUsername;
String ftpPassword;
String ftpControlEncoding;
String configFilePath = OfficeUtils.getCustomizedConfigPath(); String configFilePath = OfficeUtils.getCustomizedConfigPath();
String baseUlr;
while (true) { while (true) {
FileReader fileReader = new FileReader(configFilePath); FileReader fileReader = new FileReader(configFilePath);
BufferedReader bufferedReader = new BufferedReader(fileReader); BufferedReader bufferedReader = new BufferedReader(fileReader);
properties.load(bufferedReader); properties.load(bufferedReader);
OfficeUtils.restorePropertiesFromEnvFormat(properties);
cacheEnabled = new Boolean(properties.getProperty("cache.enabled", DEFAULT_CACHE_ENABLED));
text = properties.getProperty("simText", DEFAULT_TXT_TYPE); text = properties.getProperty("simText", DEFAULT_TXT_TYPE);
media = properties.getProperty("media", DEFAULT_MEDIA_TYPE); media = properties.getProperty("media", DEFAULT_MEDIA_TYPE);
convertedFileCharset = properties.getProperty("converted.file.charset", convertedFileCharset);
officePreviewType = properties.getProperty("office.preview.type", OfficeFilePreviewImpl.OFFICE_PREVIEW_TYPE_IMAGE); officePreviewType = properties.getProperty("office.preview.type", OfficeFilePreviewImpl.OFFICE_PREVIEW_TYPE_IMAGE);
ftpUsername = properties.getProperty("ftp.username", DEFAULT_FTP_USERNAME);
ftpPassword = properties.getProperty("ftp.password", DEFAULT_FTP_PASSWORD);
ftpControlEncoding = properties.getProperty("ftp.control.encoding", DEFAULT_FTP_CONTROL_ENCODING);
textArray = text.split(","); textArray = text.split(",");
mediaArray = media.split(","); mediaArray = media.split(",");
baseUlr = properties.getProperty("base.url", DEFAULT_BASE_URL);
ConfigConstants.setCacheEnabled(cacheEnabled);
ConfigConstants.setSimText(textArray); ConfigConstants.setSimText(textArray);
ConfigConstants.setMedia(mediaArray); ConfigConstants.setMedia(mediaArray);
ConfigConstants.setConvertedFileCharset(convertedFileCharset);
ConfigConstants.setOfficePreviewType(officePreviewType); ConfigConstants.setOfficePreviewType(officePreviewType);
ConfigConstants.setFtpUsername(ftpUsername);
ConfigConstants.setFtpPassword(ftpPassword);
ConfigConstants.setFtpControlEncoding(ftpControlEncoding);
ConfigConstants.setBaseUrl(baseUlr);
bufferedReader.close(); bufferedReader.close();
fileReader.close(); fileReader.close();
Thread.sleep(1000L); Thread.sleep(1000L);
} }
} catch (IOException | InterruptedException e) { } catch (IOException | InterruptedException e) {
LOGGER.error("读取配置文件异常{}", e); LOGGER.error("读取配置文件异常", e);
} }
} }
} }

View File

@@ -1,5 +1,8 @@
package cn.keking.filters; package cn.keking.filters;
import cn.keking.config.ConfigConstants;
import cn.keking.config.ConfigRefreshComponent;
import javax.servlet.*; import javax.servlet.*;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.io.IOException; import java.io.IOException;
@@ -19,10 +22,20 @@ public class ChinesePathFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("UTF-8"); request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8");
String baseUrl;
String baseUrlTmp = ConfigConstants.getBaseUrl();
if (baseUrlTmp != null && !ConfigRefreshComponent.DEFAULT_BASE_URL.equals(baseUrlTmp.toLowerCase())) {
if (!baseUrlTmp.endsWith("/")) {
baseUrlTmp = baseUrlTmp.concat("/");
}
baseUrl = baseUrlTmp;
} else {
StringBuilder pathBuilder = new StringBuilder(); StringBuilder pathBuilder = new StringBuilder();
pathBuilder.append(request.getScheme()).append("://").append(request.getServerName()).append(":") pathBuilder.append(request.getScheme()).append("://").append(request.getServerName()).append(":")
.append(request.getServerPort()).append(((HttpServletRequest)request).getContextPath()).append("/"); .append(request.getServerPort()).append(((HttpServletRequest) request).getContextPath()).append("/");
request.setAttribute("baseUrl", pathBuilder.toString()); baseUrl = pathBuilder.toString();
}
request.setAttribute("baseUrl", baseUrl);
chain.doFilter(request, response); chain.doFilter(request, response);
} }

View File

@@ -35,7 +35,7 @@ public class FileConverQueueTask {
@PostConstruct @PostConstruct
public void startTask(){ public void startTask(){
ExecutorService executorService = Executors.newFixedThreadPool(3); ExecutorService executorService = Executors.newFixedThreadPool(3);
executorService.submit(new ConverTask(previewFactory,cacheService,fileUtils)); executorService.submit(new ConverTask(previewFactory, cacheService, fileUtils));
logger.info("队列处理文件转换任务启动完成 "); logger.info("队列处理文件转换任务启动完成 ");
} }
@@ -47,7 +47,7 @@ public class FileConverQueueTask {
FileUtils fileUtils; FileUtils fileUtils;
public ConverTask(FilePreviewFactory previewFactory, CacheService cacheService,FileUtils fileUtils) { public ConverTask(FilePreviewFactory previewFactory, CacheService cacheService, FileUtils fileUtils) {
this.previewFactory = previewFactory; this.previewFactory = previewFactory;
this.cacheService = cacheService; this.cacheService = cacheService;
this.fileUtils=fileUtils; this.fileUtils=fileUtils;
@@ -58,13 +58,13 @@ public class FileConverQueueTask {
while (true) { while (true) {
try { try {
String url = cacheService.takeQueueTask(); String url = cacheService.takeQueueTask();
if(url!=null){ if(url != null){
FileAttribute fileAttribute=fileUtils.getFileAttribute(url); FileAttribute fileAttribute = fileUtils.getFileAttribute(url);
logger.info("正在处理转换任务,文件名称【{}】",fileAttribute.getName()); logger.info("正在处理转换任务,文件名称【{}】",fileAttribute.getName());
FileType fileType=fileAttribute.getType(); FileType fileType=fileAttribute.getType();
if(fileType.equals(FileType.compress) || fileType.equals(FileType.office)){ if(fileType.equals(FileType.compress) || fileType.equals(FileType.office)){
FilePreview filePreview=previewFactory.get(url); FilePreview filePreview=previewFactory.get(fileAttribute);
filePreview.filePreviewHandle(url,new ExtendedModelMap()); filePreview.filePreviewHandle(url, new ExtendedModelMap(), fileAttribute);
} }
} }
} catch (Exception e) { } catch (Exception e) {

View File

@@ -1,5 +1,6 @@
package cn.keking.service; package cn.keking.service;
import cn.keking.model.FileAttribute;
import org.springframework.ui.Model; import org.springframework.ui.Model;
/** /**
@@ -7,5 +8,5 @@ import org.springframework.ui.Model;
* Content : * Content :
*/ */
public interface FilePreview { public interface FilePreview {
String filePreviewHandle(String url, Model model); String filePreviewHandle(String url, Model model, FileAttribute fileAttribute);
} }

View File

@@ -5,7 +5,6 @@ import cn.keking.utils.FileUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.ui.Model;
import java.util.Map; import java.util.Map;
@@ -22,9 +21,8 @@ public class FilePreviewFactory {
@Autowired @Autowired
ApplicationContext context; ApplicationContext context;
public FilePreview get(String url) { public FilePreview get(FileAttribute fileAttribute) {
Map<String, FilePreview> filePreviewMap = context.getBeansOfType(FilePreview.class); Map<String, FilePreview> filePreviewMap = context.getBeansOfType(FilePreview.class);
FileAttribute fileAttribute = fileUtils.getFileAttribute(url);
return filePreviewMap.get(fileAttribute.getType().getInstanceName()); return filePreviewMap.get(fileAttribute.getType().getInstanceName());
} }
} }

View File

@@ -20,7 +20,7 @@ public interface CacheService {
void initPDFCachePool(Integer capacity); void initPDFCachePool(Integer capacity);
void initIMGCachePool(Integer capacity); void initIMGCachePool(Integer capacity);
public void initPdfImagesCachePool(Integer capacity); void initPdfImagesCachePool(Integer capacity);
void putPDFCache(String key, String value); void putPDFCache(String key, String value);
void putImgCache(String key, List<String> value); void putImgCache(String key, List<String> value);
Map<String, String> getPDFCache(); Map<String, String> getPDFCache();
@@ -30,7 +30,11 @@ public interface CacheService {
Integer getPdfImageCache(String key); Integer getPdfImageCache(String key);
void putPdfImageCache(String pdfFilePath, int num); void putPdfImageCache(String pdfFilePath, int num);
void cleanCache();
void addQueueTask(String url); void addQueueTask(String url);
String takeQueueTask() throws InterruptedException; String takeQueueTask() throws InterruptedException;
} }

View File

@@ -116,6 +116,13 @@ public class CacheServiceJDKImpl implements CacheService {
pdfImagesCache.put(pdfFilePath, num); pdfImagesCache.put(pdfFilePath, num);
} }
@Override
public void cleanCache() {
initPDFCachePool(CacheService.DEFAULT_PDF_CAPACITY);
initIMGCachePool(CacheService.DEFAULT_IMG_CAPACITY);
initPdfImagesCachePool(CacheService.DEFAULT_PDFIMG_CAPACITY);
}
@Override @Override
public void addQueueTask(String url) { public void addQueueTask(String url) {
blockingQueue.add(url); blockingQueue.add(url);

View File

@@ -94,6 +94,13 @@ public class CacheServiceRedisImpl implements CacheService {
convertedList.fastPut(pdfFilePath, num); convertedList.fastPut(pdfFilePath, num);
} }
@Override
public void cleanCache() {
cleanPdfCache();
cleanImgCache();
cleanPdfImgCache();
}
@Override @Override
public void addQueueTask(String url) { public void addQueueTask(String url) {
RBlockingQueue<String> queue = redissonClient.getBlockingQueue(FileConverQueueTask.queueTaskName); RBlockingQueue<String> queue = redissonClient.getBlockingQueue(FileConverQueueTask.queueTaskName);
@@ -105,4 +112,19 @@ public class CacheServiceRedisImpl implements CacheService {
RBlockingQueue<String> queue = redissonClient.getBlockingQueue(FileConverQueueTask.queueTaskName); RBlockingQueue<String> queue = redissonClient.getBlockingQueue(FileConverQueueTask.queueTaskName);
return queue.take(); return queue.take();
} }
private void cleanPdfCache() {
RMapCache<String, String> pdfCache = redissonClient.getMapCache(REDIS_FILE_PREVIEW_PDF_KEY);
pdfCache.clear();
}
private void cleanImgCache() {
RMapCache<String, List<String>> imgCache = redissonClient.getMapCache(REDIS_FILE_PREVIEW_IMGS_KEY);
imgCache.clear();
}
private void cleanPdfImgCache() {
RMapCache<String, Integer> pdfImg = redissonClient.getMapCache(REDIS_FILE_PREVIEW_PDF_IMGS_KEY);
pdfImg.clear();
}
} }

View File

@@ -92,7 +92,7 @@ public class CacheServiceRocksDBImpl implements CacheService {
try { try {
Map<String, List<String>> imgCacheItem = getImgCache(); Map<String, List<String>> imgCacheItem = getImgCache();
imgCacheItem.put(key, value); imgCacheItem.put(key, value);
db.put(REDIS_FILE_PREVIEW_PDF_KEY.getBytes(), toByteArray(imgCacheItem)); db.put(REDIS_FILE_PREVIEW_IMGS_KEY.getBytes(), toByteArray(imgCacheItem));
} catch (RocksDBException | IOException e) { } catch (RocksDBException | IOException e) {
LOGGER.error("Put into RocksDB Exception" + e); LOGGER.error("Put into RocksDB Exception" + e);
} }
@@ -179,6 +179,17 @@ public class CacheServiceRocksDBImpl implements CacheService {
} }
} }
@Override
public void cleanCache() {
try {
cleanPdfCache();
cleanImgCache();
cleanPdfImgCache();
} catch (IOException | RocksDBException e) {
LOGGER.error("Clean Cache Exception" + e);
}
}
@Override @Override
public void addQueueTask(String url) { public void addQueueTask(String url) {
blockingQueue.add(url); blockingQueue.add(url);
@@ -210,4 +221,19 @@ public class CacheServiceRocksDBImpl implements CacheService {
bis.close(); bis.close();
return obj; return obj;
} }
private void cleanPdfCache() throws IOException, RocksDBException {
Map<String, String> initPDFCache = new HashMap<>();
db.put(REDIS_FILE_PREVIEW_PDF_KEY.getBytes(), toByteArray(initPDFCache));
}
private void cleanImgCache() throws IOException, RocksDBException {
Map<String, List<String>> initIMGCache = new HashMap<>();
db.put(REDIS_FILE_PREVIEW_IMGS_KEY.getBytes(), toByteArray(initIMGCache));
}
private void cleanPdfImgCache() throws IOException, RocksDBException {
Map<String, Integer> initPDFIMGCache = new HashMap<>();
db.put(REDIS_FILE_PREVIEW_PDF_IMGS_KEY.getBytes(), toByteArray(initPDFIMGCache));
}
} }

View File

@@ -1,5 +1,6 @@
package cn.keking.service.impl; package cn.keking.service.impl;
import cn.keking.config.ConfigConstants;
import cn.keking.model.FileAttribute; import cn.keking.model.FileAttribute;
import cn.keking.model.ReturnResponse; import cn.keking.model.ReturnResponse;
import cn.keking.service.FilePreview; import cn.keking.service.FilePreview;
@@ -28,15 +29,13 @@ public class CompressFilePreviewImpl implements FilePreview{
ZipReader zipReader; ZipReader zipReader;
@Override @Override
public String filePreviewHandle(String url, Model model) { public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
FileAttribute fileAttribute=fileUtils.getFileAttribute(url);
String fileName=fileAttribute.getName(); String fileName=fileAttribute.getName();
String decodedUrl=fileAttribute.getDecodedUrl();
String suffix=fileAttribute.getSuffix(); String suffix=fileAttribute.getSuffix();
String fileTree = null; String fileTree = null;
// 判断文件名是否存在(redis缓存读取) // 判断文件名是否存在(redis缓存读取)
if (!StringUtils.hasText(fileUtils.getConvertedFile(fileName))) { if (!StringUtils.hasText(fileUtils.getConvertedFile(fileName)) || !ConfigConstants.isCacheEnabled()) {
ReturnResponse<String> response = downloadUtils.downLoad(decodedUrl, suffix, fileName); ReturnResponse<String> response = downloadUtils.downLoad(fileAttribute, fileName);
if (0 != response.getCode()) { if (0 != response.getCode()) {
model.addAttribute("fileType", suffix); model.addAttribute("fileType", suffix);
model.addAttribute("msg", response.getMsg()); model.addAttribute("msg", response.getMsg());
@@ -50,7 +49,7 @@ public class CompressFilePreviewImpl implements FilePreview{
} else if ("7z".equalsIgnoreCase(suffix)) { } else if ("7z".equalsIgnoreCase(suffix)) {
fileTree = zipReader.read7zFile(filePath, fileName); fileTree = zipReader.read7zFile(filePath, fileName);
} }
if (fileTree != null && !"null".equals(fileTree)) { if (fileTree != null && !"null".equals(fileTree) && ConfigConstants.isCacheEnabled()) {
fileUtils.addConvertedFile(fileName, fileTree); fileUtils.addConvertedFile(fileName, fileTree);
} }
} else { } else {

View File

@@ -19,9 +19,8 @@ public class MediaFilePreviewImpl implements FilePreview {
FileUtils fileUtils; FileUtils fileUtils;
@Override @Override
public String filePreviewHandle(String url, Model model) { public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
model.addAttribute("mediaUrl", url); model.addAttribute("mediaUrl", url);
FileAttribute fileAttribute=fileUtils.getFileAttribute(url);
String suffix=fileAttribute.getSuffix(); String suffix=fileAttribute.getSuffix();
if ("flv".equalsIgnoreCase(suffix)) { if ("flv".equalsIgnoreCase(suffix)) {
return "flv"; return "flv";

View File

@@ -9,9 +9,7 @@ import cn.keking.utils.FileUtils;
import cn.keking.utils.OfficeToPdf; import cn.keking.utils.OfficeToPdf;
import cn.keking.utils.PdfUtils; import cn.keking.utils.PdfUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.ui.ExtendedModelMap;
import org.springframework.ui.Model; import org.springframework.ui.Model;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
@@ -44,44 +42,38 @@ public class OfficeFilePreviewImpl implements FilePreview {
public static final String OFFICE_PREVIEW_TYPE_ALLIMAGES = "allImages"; public static final String OFFICE_PREVIEW_TYPE_ALLIMAGES = "allImages";
@Override @Override
public String filePreviewHandle(String url, Model model) { public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
// 预览Type参数传了就取参数的没传取系统默认 // 预览Type参数传了就取参数的没传取系统默认
String officePreviewType = model.asMap().get("officePreviewType") == null ? ConfigConstants.getOfficePreviewType() : model.asMap().get("officePreviewType").toString(); String officePreviewType = model.asMap().get("officePreviewType") == null ? ConfigConstants.getOfficePreviewType() : model.asMap().get("officePreviewType").toString();
String originUrl = model.asMap().get("originUrl").toString(); String originUrl = (String) model.asMap().get("originUrl");
FileAttribute fileAttribute=fileUtils.getFileAttribute(url);
String suffix=fileAttribute.getSuffix(); String suffix=fileAttribute.getSuffix();
String fileName=fileAttribute.getName(); String fileName=fileAttribute.getName();
String decodedUrl=fileAttribute.getDecodedUrl();
boolean isHtml = suffix.equalsIgnoreCase("xls") || suffix.equalsIgnoreCase("xlsx"); boolean isHtml = suffix.equalsIgnoreCase("xls") || suffix.equalsIgnoreCase("xlsx");
String pdfName = fileName.substring(0, fileName.lastIndexOf(".") + 1) + (isHtml ? "html" : "pdf"); String pdfName = fileName.substring(0, fileName.lastIndexOf(".") + 1) + (isHtml ? "html" : "pdf");
String outFilePath = fileDir + pdfName; String outFilePath = fileDir + pdfName;
// 判断之前是否已转换过,如果转换过,直接返回,否则执行转换 // 判断之前是否已转换过,如果转换过,直接返回,否则执行转换
if (!fileUtils.listConvertedFiles().containsKey(pdfName)) { if (!fileUtils.listConvertedFiles().containsKey(pdfName) || !ConfigConstants.isCacheEnabled()) {
String filePath = fileDir + fileName; String filePath = fileDir + fileName;
if (!new File(filePath).exists()) { ReturnResponse<String> response = downloadUtils.downLoad(fileAttribute, null);
ReturnResponse<String> response = downloadUtils.downLoad(decodedUrl, suffix, null);
if (0 != response.getCode()) { if (0 != response.getCode()) {
model.addAttribute("fileType", suffix); model.addAttribute("fileType", suffix);
model.addAttribute("msg", response.getMsg()); model.addAttribute("msg", response.getMsg());
return "fileNotSupported"; return "fileNotSupported";
} }
filePath = response.getContent(); filePath = response.getContent();
}
if (StringUtils.hasText(outFilePath)) { if (StringUtils.hasText(outFilePath)) {
officeToPdf.openOfficeToPDF(filePath, outFilePath); officeToPdf.openOfficeToPDF(filePath, outFilePath);
File f = new File(filePath);
if (f.exists()) {
f.delete();
}
if (isHtml) { if (isHtml) {
// 对转换后的文件进行操作(改变编码方式) // 对转换后的文件进行操作(改变编码方式)
fileUtils.doActionConvertedFile(outFilePath); fileUtils.doActionConvertedFile(outFilePath);
} }
if (ConfigConstants.isCacheEnabled()) {
// 加入缓存 // 加入缓存
fileUtils.addConvertedFile(pdfName, fileUtils.getRelativePath(outFilePath)); fileUtils.addConvertedFile(pdfName, fileUtils.getRelativePath(outFilePath));
} }
} }
if (!isHtml && (OFFICE_PREVIEW_TYPE_IMAGE.equals(officePreviewType) || OFFICE_PREVIEW_TYPE_ALLIMAGES.equals(officePreviewType))) { }
if (!isHtml && originUrl != null && (OFFICE_PREVIEW_TYPE_IMAGE.equals(officePreviewType) || OFFICE_PREVIEW_TYPE_ALLIMAGES.equals(officePreviewType))) {
List<String> imageUrls = pdfUtils.pdf2jpg(outFilePath, pdfName, originUrl); List<String> imageUrls = pdfUtils.pdf2jpg(outFilePath, pdfName, originUrl);
if (imageUrls == null || imageUrls.size() < 1) { if (imageUrls == null || imageUrls.size() < 1) {
model.addAttribute("msg", "office转图片异常请联系管理员"); model.addAttribute("msg", "office转图片异常请联系管理员");

View File

@@ -17,9 +17,7 @@ public class OtherFilePreviewImpl implements FilePreview {
FileUtils fileUtils; FileUtils fileUtils;
@Override @Override
public String filePreviewHandle(String url, Model model) { public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
FileAttribute fileAttribute=fileUtils.getFileAttribute(url);
model.addAttribute("fileType",fileAttribute.getSuffix()); model.addAttribute("fileType",fileAttribute.getSuffix());
model.addAttribute("msg", "系统还不支持该格式文件的在线预览," + model.addAttribute("msg", "系统还不支持该格式文件的在线预览," +
"如有需要请按下方显示的邮箱地址联系系统维护人员"); "如有需要请按下方显示的邮箱地址联系系统维护人员");

View File

@@ -34,9 +34,7 @@ public class PdfFilePreviewImpl implements FilePreview{
String fileDir = ConfigConstants.getFileDir(); String fileDir = ConfigConstants.getFileDir();
@Override @Override
public String filePreviewHandle(String url, Model model) { public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
FileAttribute fileAttribute=fileUtils.getFileAttribute(url);
String decodedUrl=fileAttribute.getDecodedUrl();
String suffix=fileAttribute.getSuffix(); String suffix=fileAttribute.getSuffix();
String fileName=fileAttribute.getName(); String fileName=fileAttribute.getName();
String officePreviewType = model.asMap().get("officePreviewType") == null ? ConfigConstants.getOfficePreviewType() : model.asMap().get("officePreviewType").toString(); String officePreviewType = model.asMap().get("officePreviewType") == null ? ConfigConstants.getOfficePreviewType() : model.asMap().get("officePreviewType").toString();
@@ -46,15 +44,13 @@ public class PdfFilePreviewImpl implements FilePreview{
String outFilePath = fileDir + pdfName; String outFilePath = fileDir + pdfName;
if (OfficeFilePreviewImpl.OFFICE_PREVIEW_TYPE_IMAGE.equals(officePreviewType) || OfficeFilePreviewImpl.OFFICE_PREVIEW_TYPE_ALLIMAGES.equals(officePreviewType)) { if (OfficeFilePreviewImpl.OFFICE_PREVIEW_TYPE_IMAGE.equals(officePreviewType) || OfficeFilePreviewImpl.OFFICE_PREVIEW_TYPE_ALLIMAGES.equals(officePreviewType)) {
//当文件不存在时,就去下载 //当文件不存在时,就去下载
if (!new File(outFilePath).exists()) { ReturnResponse<String> response = downloadUtils.downLoad(fileAttribute, fileName);
ReturnResponse<String> response = downloadUtils.downLoad(decodedUrl, suffix, fileName);
if (0 != response.getCode()) { if (0 != response.getCode()) {
model.addAttribute("fileType", suffix); model.addAttribute("fileType", suffix);
model.addAttribute("msg", response.getMsg()); model.addAttribute("msg", response.getMsg());
return "fileNotSupported"; return "fileNotSupported";
} }
outFilePath = response.getContent(); outFilePath = response.getContent();
}
List<String> imageUrls = pdfUtils.pdf2jpg(outFilePath, pdfName, originUrl); List<String> imageUrls = pdfUtils.pdf2jpg(outFilePath, pdfName, originUrl);
if (imageUrls == null || imageUrls.size() < 1) { if (imageUrls == null || imageUrls.size() < 1) {
model.addAttribute("msg", "pdf转图片异常请联系管理员"); model.addAttribute("msg", "pdf转图片异常请联系管理员");

View File

@@ -1,5 +1,6 @@
package cn.keking.service.impl; package cn.keking.service.impl;
import cn.keking.model.FileAttribute;
import cn.keking.service.FilePreview; import cn.keking.service.FilePreview;
import cn.keking.utils.FileUtils; import cn.keking.utils.FileUtils;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
@@ -21,7 +22,7 @@ public class PictureFilePreviewImpl implements FilePreview {
FileUtils fileUtils; FileUtils fileUtils;
@Override @Override
public String filePreviewHandle(String url, Model model) { public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
String fileKey=(String) RequestContextHolder.currentRequestAttributes().getAttribute("fileKey",0); String fileKey=(String) RequestContextHolder.currentRequestAttributes().getAttribute("fileKey",0);
List imgUrls = Lists.newArrayList(url); List imgUrls = Lists.newArrayList(url);
try{ try{

View File

@@ -9,6 +9,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.ui.Model; import org.springframework.ui.Model;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
/** /**
* Created by kl on 2018/1/17. * Created by kl on 2018/1/17.
* Content :处理文本文件 * Content :处理文本文件
@@ -23,8 +27,7 @@ public class SimTextFilePreviewImpl implements FilePreview{
FileUtils fileUtils; FileUtils fileUtils;
@Override @Override
public String filePreviewHandle(String url, Model model){ public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute){
FileAttribute fileAttribute=fileUtils.getFileAttribute(url);
String decodedUrl=fileAttribute.getDecodedUrl(); String decodedUrl=fileAttribute.getDecodedUrl();
String fileName=fileAttribute.getName(); String fileName=fileAttribute.getName();
ReturnResponse<String> response = simTextUtil.readSimText(decodedUrl, fileName); ReturnResponse<String> response = simTextUtil.readSimText(decodedUrl, fileName);
@@ -33,7 +36,16 @@ public class SimTextFilePreviewImpl implements FilePreview{
model.addAttribute("fileType",fileAttribute.getSuffix()); model.addAttribute("fileType",fileAttribute.getSuffix());
return "fileNotSupported"; return "fileNotSupported";
} }
model.addAttribute("ordinaryUrl", response.getMsg()); try {
File originFile = new File(response.getContent());
File previewFile = new File(response.getContent() + ".txt");
Files.copy(originFile.toPath(), previewFile.toPath());
} catch (IOException e) {
model.addAttribute("msg", e.getLocalizedMessage());
model.addAttribute("fileType",fileAttribute.getSuffix());
return "fileNotSupported";
}
model.addAttribute("ordinaryUrl", response.getMsg() + ".txt");
return "txt"; return "txt";
} }

View File

@@ -1,8 +1,14 @@
package cn.keking.utils; package cn.keking.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File; import java.io.File;
public class DeleteFileUtil { public class DeleteFileUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(DeleteFileUtil.class);
/** /**
* 删除单个文件 * 删除单个文件
* *
@@ -15,14 +21,14 @@ public class DeleteFileUtil {
// 如果文件路径所对应的文件存在,并且是一个文件,则直接删除 // 如果文件路径所对应的文件存在,并且是一个文件,则直接删除
if (file.exists() && file.isFile()) { if (file.exists() && file.isFile()) {
if (file.delete()) { if (file.delete()) {
System.out.println("删除单个文件" + fileName + "成功!"); LOGGER.info("删除单个文件" + fileName + "成功!");
return true; return true;
} else { } else {
System.out.println("删除单个文件" + fileName + "失败!"); LOGGER.info("删除单个文件" + fileName + "失败!");
return false; return false;
} }
} else { } else {
System.out.println("删除单个文件失败:" + fileName + "不存在!"); LOGGER.info("删除单个文件失败:" + fileName + "不存在!");
return false; return false;
} }
} }
@@ -43,7 +49,7 @@ public class DeleteFileUtil {
File dirFile = new File(dir); File dirFile = new File(dir);
// 如果dir对应的文件不存在或者不是一个目录则退出 // 如果dir对应的文件不存在或者不是一个目录则退出
if ((!dirFile.exists()) || (!dirFile.isDirectory())) { if ((!dirFile.exists()) || (!dirFile.isDirectory())) {
System.out.println("删除目录失败:" + dir + "不存在!"); LOGGER.info("删除目录失败:" + dir + "不存在!");
return false; return false;
} }
boolean flag = true; boolean flag = true;
@@ -65,7 +71,7 @@ public class DeleteFileUtil {
} }
} }
if (!flag) { if (!flag) {
System.out.println("删除目录失败!"); LOGGER.info("删除目录失败!");
return false; return false;
} }
return true; return true;

View File

@@ -1,7 +1,11 @@
package cn.keking.utils; package cn.keking.utils;
import cn.keking.config.ConfigConstants; import cn.keking.config.ConfigConstants;
import cn.keking.model.FileAttribute;
import cn.keking.model.ReturnResponse; import cn.keking.model.ReturnResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.io.*; import java.io.*;
import java.net.*; import java.net.*;
@@ -13,7 +17,16 @@ import java.util.UUID;
@Component @Component
public class DownloadUtils { public class DownloadUtils {
String fileDir = ConfigConstants.getFileDir(); private static final Logger LOGGER = LoggerFactory.getLogger(DownloadUtils.class);
private String fileDir = ConfigConstants.getFileDir();
@Autowired
private FileUtils fileUtils;
private static final String URL_PARAM_FTP_USERNAME = "ftp.username";
private static final String URL_PARAM_FTP_PASSWORD = "ftp.password";
private static final String URL_PARAM_FTP_CONTROL_ENCODING = "ftp.control.encoding";
/** /**
* 一开始测试的时候发现有些文件没有下载下来,而有些可以;当时也是郁闷了好一阵,但是最终还是不得解 * 一开始测试的时候发现有些文件没有下载下来,而有些可以;当时也是郁闷了好一阵,但是最终还是不得解
@@ -21,18 +34,21 @@ public class DownloadUtils {
* 应该是转义出了问题url转义中会把+号当成空格来计算所以才会出现这种情况遂想要通过整体替换空格为加号因为url * 应该是转义出了问题url转义中会把+号当成空格来计算所以才会出现这种情况遂想要通过整体替换空格为加号因为url
* 中的参数部分是不会出现空格的但是文件名中就不好确定了所以只对url参数部分做替换 * 中的参数部分是不会出现空格的但是文件名中就不好确定了所以只对url参数部分做替换
* 注: 针对URLEncoder.encode(s,charset)会将空格转成+的情况需要做下面的替换工作 * 注: 针对URLEncoder.encode(s,charset)会将空格转成+的情况需要做下面的替换工作
* @param urlAddress * @param fileAttribute
* @param type
* @return * @return
*/ */
public ReturnResponse<String> downLoad(String urlAddress, String type, String fileName){ public ReturnResponse<String> downLoad(FileAttribute fileAttribute, String fileName) {
String urlAddress = fileAttribute.getDecodedUrl();
String type = fileAttribute.getSuffix();
ReturnResponse<String> response = new ReturnResponse<>(0, "下载成功!!!", ""); ReturnResponse<String> response = new ReturnResponse<>(0, "下载成功!!!", "");
URL url = null; URL url = null;
try { try {
urlAddress = replacePlusMark(urlAddress); urlAddress = replacePlusMark(urlAddress);
urlAddress = encodeUrlParam(urlAddress); urlAddress = encodeUrlParam(urlAddress);
// 因为tomcat不能处理'+'号,所以讲'+'号替换成'%20%' // 因为tomcat不能处理'+'号,所以讲'+'号替换成'%20%'
// 也不能处理空格
urlAddress = urlAddress.replaceAll("\\+", "%20"); urlAddress = urlAddress.replaceAll("\\+", "%20");
urlAddress = urlAddress.replaceAll(" ", "%20");
url = new URL(urlAddress); url = new URL(urlAddress);
} catch (MalformedURLException e) { } catch (MalformedURLException e) {
e.printStackTrace(); e.printStackTrace();
@@ -40,7 +56,7 @@ public class DownloadUtils {
UUID uuid = UUID.randomUUID(); UUID uuid = UUID.randomUUID();
if (null == fileName) { if (null == fileName) {
fileName = uuid+ "."+type; fileName = uuid+ "."+type;
}else { // 文件后缀不一致时以type为准(针对simText【将类txt文件转为txt】) } else { // 文件后缀不一致时以type为准(针对simText【将类txt文件转为txt】)
fileName = fileName.replace(fileName.substring(fileName.lastIndexOf(".") + 1), type); fileName = fileName.replace(fileName.substring(fileName.lastIndexOf(".") + 1), type);
} }
String realPath = fileDir + fileName; String realPath = fileDir + fileName;
@@ -49,6 +65,12 @@ public class DownloadUtils {
dirFile.mkdirs(); dirFile.mkdirs();
} }
try { try {
if ("ftp".equals(url.getProtocol())) {
String ftpUsername = fileUtils.getUrlParameterReg(fileAttribute.getUrl(), URL_PARAM_FTP_USERNAME);
String ftpPassword = fileUtils.getUrlParameterReg(fileAttribute.getUrl(), URL_PARAM_FTP_PASSWORD);
String ftpControlEncoding = fileUtils.getUrlParameterReg(fileAttribute.getUrl(), URL_PARAM_FTP_CONTROL_ENCODING);
FtpUtils.download(fileAttribute.getUrl(), realPath, ftpUsername, ftpPassword, ftpControlEncoding);
} else {
URLConnection connection = url.openConnection(); URLConnection connection = url.openConnection();
InputStream in = connection.getInputStream(); InputStream in = connection.getInputStream();
@@ -60,6 +82,7 @@ public class DownloadUtils {
} }
os.close(); os.close();
in.close(); in.close();
}
response.setContent(realPath); response.setContent(realPath);
// 同样针对类txt文件如果成功msg包含的是转换后的文件名 // 同样针对类txt文件如果成功msg包含的是转换后的文件名
response.setMsg(fileName); response.setMsg(fileName);
@@ -68,15 +91,14 @@ public class DownloadUtils {
if("txt".equals(type)){ if("txt".equals(type)){
convertTextPlainFileCharsetToUtf8(realPath); convertTextPlainFileCharsetToUtf8(realPath);
} }
return response; return response;
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); LOGGER.error("文件下载失败", e);
response.setCode(1); response.setCode(1);
response.setContent(null); response.setContent(null);
if (e instanceof FileNotFoundException) { if (e instanceof FileNotFoundException) {
response.setMsg("文件不存在!!!"); response.setMsg("文件不存在!!!");
}else { } else {
response.setMsg(e.getMessage()); response.setMsg(e.getMessage());
} }
return response; return response;
@@ -103,30 +125,35 @@ public class DownloadUtils {
* 对最有一个路径进行转码 * 对最有一个路径进行转码
* @param urlAddress * @param urlAddress
* http://192.168.2.111:8013/demo/Handle中文.zip * http://192.168.2.111:8013/demo/Handle中文.zip
* http://192.168.2.111:8013/download?id=1&filename=中文.zip
* @return * @return
*/ */
private String encodeUrlParam(String urlAddress) {
String newUrl = ""; private String encodeUrlParam(String urlAddress){
StringBuffer sb = new StringBuffer();
for (int i = 0; i < urlAddress.length(); i++) {
char c = urlAddress.charAt(i);
if (c >= 0 && c <= 255) {
sb.append(c);
} else {
byte[] b;
try { try {
String path = ""; //指定需要的编码类型
String param = ""; b = String.valueOf(c).getBytes("utf-8");
if (urlAddress.contains("?")) { } catch (Exception ex) {
path = urlAddress.substring(0, urlAddress.indexOf("?")); System.out.println(ex);
param = urlAddress.substring(urlAddress.indexOf("?")); b = new byte[0];
}else {
path = urlAddress;
} }
String lastPath = path.substring(path.lastIndexOf("/") + 1); for (int j = 0; j < b.length; j++) {
String leftPath = path.substring(0, path.lastIndexOf("/") + 1); int k = b[j];
String encodeLastPath = URLEncoder.encode(lastPath, "UTF-8"); if (k < 0) {
newUrl += leftPath + encodeLastPath; k += 256;
if (urlAddress.contains("?")) {
newUrl += param;
} }
} catch (UnsupportedEncodingException e) { sb.append("%" + Integer.toHexString(k).toUpperCase());
e.printStackTrace();
} }
return newUrl; }
}
return sb.toString();
} }

View File

@@ -9,11 +9,12 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.io.*; import java.io.*;
import java.net.URLDecoder;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -24,6 +25,9 @@ import java.util.Map;
*/ */
@Component @Component
public class FileUtils { public class FileUtils {
public static final String DEFAULT_CONVERTER_CHARSET = System.getProperty("sun.jnu.encoding");
Logger log= LoggerFactory.getLogger(getClass()); Logger log= LoggerFactory.getLogger(getClass());
@Autowired @Autowired
@@ -63,10 +67,14 @@ public class FileUtils {
* @return * @return
*/ */
public FileType typeFromUrl(String url) { public FileType typeFromUrl(String url) {
String[] simText = ConfigConstants.getSimText();
String[] media = ConfigConstants.getMedia();
String nonPramStr = url.substring(0, url.indexOf("?") != -1 ? url.indexOf("?") : url.length()); String nonPramStr = url.substring(0, url.indexOf("?") != -1 ? url.indexOf("?") : url.length());
String fileName = nonPramStr.substring(nonPramStr.lastIndexOf("/") + 1); String fileName = nonPramStr.substring(nonPramStr.lastIndexOf("/") + 1);
return typeFromFileName(fileName);
}
private FileType typeFromFileName(String fileName) {
String[] simText = ConfigConstants.getSimText();
String[] media = ConfigConstants.getMedia();
String fileType = fileName.substring(fileName.lastIndexOf(".") + 1); String fileType = fileName.substring(fileName.lastIndexOf(".") + 1);
if (listPictureTypes().contains(fileType.toLowerCase())) { if (listPictureTypes().contains(fileType.toLowerCase())) {
return FileType.picture; return FileType.picture;
@@ -228,9 +236,8 @@ public class FileUtils {
*/ */
public void doActionConvertedFile(String outFilePath) { public void doActionConvertedFile(String outFilePath) {
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
String charset = ConfigConstants.getConvertedFileCharset();
try (InputStream inputStream = new FileInputStream(outFilePath); try (InputStream inputStream = new FileInputStream(outFilePath);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, charset))){ BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, DEFAULT_CONVERTER_CHARSET))){
String line; String line;
while(null != (line = reader.readLine())){ while(null != (line = reader.readLine())){
if (line.contains("charset=gb2312")) { if (line.contains("charset=gb2312")) {
@@ -241,7 +248,7 @@ public class FileUtils {
// 添加sheet控制头 // 添加sheet控制头
sb.append("<script src=\"js/jquery-3.0.0.min.js\" type=\"text/javascript\"></script>"); sb.append("<script src=\"js/jquery-3.0.0.min.js\" type=\"text/javascript\"></script>");
sb.append("<script src=\"js/excel.header.js\" type=\"text/javascript\"></script>"); sb.append("<script src=\"js/excel.header.js\" type=\"text/javascript\"></script>");
sb.append("<link rel=\"stylesheet\" href=\"http://cdn.static.runoob.com/libs/bootstrap/3.3.7/css/bootstrap.min.css\">"); sb.append("<link rel=\"stylesheet\" href=\"//cdn.static.runoob.com/libs/bootstrap/3.3.7/css/bootstrap.min.css\">");
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
e.printStackTrace(); e.printStackTrace();
} catch (IOException e) { } catch (IOException e) {
@@ -265,22 +272,76 @@ public class FileUtils {
private String suffixFromUrl(String url) { private String suffixFromUrl(String url) {
String nonPramStr = url.substring(0, url.indexOf("?") != -1 ? url.indexOf("?") : url.length()); String nonPramStr = url.substring(0, url.indexOf("?") != -1 ? url.indexOf("?") : url.length());
String fileName = nonPramStr.substring(nonPramStr.lastIndexOf("/") + 1); String fileName = nonPramStr.substring(nonPramStr.lastIndexOf("/") + 1);
return suffixFromFileName(fileName);
}
private String suffixFromFileName(String fileName) {
String fileType = fileName.substring(fileName.lastIndexOf(".") + 1); String fileType = fileName.substring(fileName.lastIndexOf(".") + 1);
return fileType; return fileType;
} }
public FileAttribute getFileAttribute(String url) { /**
String decodedUrl=null; * 获取url中的参数
try { * @param url
decodedUrl = URLDecoder.decode(url, "utf-8"); * @param name
}catch (UnsupportedEncodingException e){ * @return
log.debug("url解码失败"); */
public String getUrlParameterReg(String url, String name) {
Map<String, String> mapRequest = new HashMap();
String strUrlParam = truncateUrlPage(url);
if (strUrlParam == null) {
return "";
} }
// 路径转码 //每个键值为一组
FileType type = typeFromUrl(url); String[] arrSplit=strUrlParam.split("[&]");
String suffix = suffixFromUrl(url); for(String strSplit:arrSplit) {
// 抽取文件并返回文件列表 String[] arrSplitEqual= strSplit.split("[=]");
String fileName = getFileNameFromURL(decodedUrl); //解析出键值
return new FileAttribute(type,suffix,fileName,url,decodedUrl); if(arrSplitEqual.length > 1) {
//正确解析
mapRequest.put(arrSplitEqual[0], arrSplitEqual[1]);
} else if (!arrSplitEqual[0].equals("")) {
//只有参数没有值,不加入
mapRequest.put(arrSplitEqual[0], "");
}
}
return mapRequest.get(name);
}
/**
* 去掉url中的路径留下请求参数部分
* @param strURL url地址
* @return url请求参数部分
*/
private String truncateUrlPage(String strURL) {
String strAllParam = null;
strURL = strURL.trim();
String[] arrSplit = strURL.split("[?]");
if(strURL.length() > 1) {
if(arrSplit.length > 1) {
if(arrSplit[1] != null) {
strAllParam=arrSplit[1];
}
}
}
return strAllParam;
}
public FileAttribute getFileAttribute(String url) {
String fileName;
FileType type;
String suffix;
String fullFileName = getUrlParameterReg(url, "fullfilename");
if (!StringUtils.isEmpty(fullFileName)) {
fileName = fullFileName;
type = typeFromFileName(fileName);
suffix = suffixFromFileName(fileName);
} else {
fileName = getFileNameFromURL(url);
type = typeFromUrl(url);
suffix = suffixFromUrl(url);
}
return new FileAttribute(type,suffix,fileName,url,url);
} }
} }

View File

@@ -0,0 +1,57 @@
package cn.keking.utils;
import cn.keking.config.ConfigConstants;
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;
/**
* @auther: chenjh
* @since: 2019/6/18 14:36
*/
public class FtpUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(FtpUtils.class);
public static FTPClient connect(String host, int port, String username, String password, String controlEncoding) throws IOException {
FTPClient ftpClient = new FTPClient();
ftpClient.connect(host, port);
if (!StringUtils.isEmpty(username) && !StringUtils.isEmpty(password)) {
ftpClient.login(username, password);
}
int reply = ftpClient.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftpClient.disconnect();
}
ftpClient.setControlEncoding(controlEncoding);
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
return ftpClient;
}
public static void download(String ftpUrl, String localFilePath, String ftpUsername, String ftpPassword, String ftpControlEncoding) throws IOException {
String username = StringUtils.isEmpty(ftpUsername) ? ConfigConstants.getFtpUsername() : ftpUsername;
String password = StringUtils.isEmpty(ftpPassword) ? ConfigConstants.getFtpPassword() : ftpPassword;
String controlEncoding = StringUtils.isEmpty(ftpControlEncoding) ? ConfigConstants.getFtpControlEncoding() : ftpControlEncoding;
URL url = new URL(ftpUrl);
String host = url.getHost();
int port = (url.getPort() == -1) ? url.getDefaultPort() : url.getPort();
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);
ftpClient.enterLocalPassiveMode();
boolean downloadResult = ftpClient.retrieveFile(new String(remoteFilePath.getBytes(controlEncoding), "ISO-8859-1"), outputStream);
LOGGER.debug("FTP download result {}", downloadResult);
outputStream.flush();
outputStream.close();
ftpClient.logout();
ftpClient.disconnect();
}
}

View File

@@ -1,15 +1,35 @@
package cn.keking.utils; package cn.keking.utils;
import cn.keking.config.ConfigConstants; import cn.keking.config.ConfigConstants;
import cn.keking.service.cache.CacheService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/**
* @auther: chenjh
* @since: 2019/6/11 7:45
*/
@Component @Component
@ConditionalOnExpression("'${cache.clean.enabled:false}'.equals('true')")
public class ShedulerClean { public class ShedulerClean {
String fileDir = ConfigConstants.getFileDir();
// @Scheduled(cron = "0 0 23 * * ?") //每晚23点执行一次 private static final Logger LOGGER = LoggerFactory.getLogger(ShedulerClean.class);
public void clean(){
System.out.println("执行一次清空文件夹"); @Autowired
private CacheService cacheService;
private String fileDir = ConfigConstants.getFileDir();
//默认每晚3点执行一次
@Scheduled(cron = "${cache.clean.cron:0 0 3 * * ?}")
public void clean() {
LOGGER.info("Cache clean start");
cacheService.cleanCache();
DeleteFileUtil.deleteDirectory(fileDir); DeleteFileUtil.deleteDirectory(fileDir);
LOGGER.info("Cache clean end");
} }
} }

View File

@@ -1,6 +1,7 @@
package cn.keking.utils; package cn.keking.utils;
import cn.keking.config.ConfigConstants; import cn.keking.config.ConfigConstants;
import cn.keking.model.FileAttribute;
import cn.keking.model.ReturnResponse; import cn.keking.model.ReturnResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -12,12 +13,14 @@ import org.springframework.stereotype.Component;
*/ */
@Component @Component
public class SimTextUtil { public class SimTextUtil {
String fileDir = ConfigConstants.getFileDir();
@Autowired @Autowired
DownloadUtils downloadUtils; private FileUtils fileUtils;
@Autowired
private DownloadUtils downloadUtils;
public ReturnResponse<String> readSimText(String url, String fileName){ public ReturnResponse<String> readSimText(String url, String fileName){
ReturnResponse<String> response = downloadUtils.downLoad(url, "txt", fileName); FileAttribute fileAttribute = fileUtils.getFileAttribute(url);
ReturnResponse<String> response = downloadUtils.downLoad(fileAttribute, fileName);
return response; return response;
} }
} }

View File

@@ -37,7 +37,19 @@ public class FileController {
@RequestMapping(value = "fileUpload", method = RequestMethod.POST) @RequestMapping(value = "fileUpload", method = RequestMethod.POST)
public String fileUpload(@RequestParam("file") MultipartFile file, public String fileUpload(@RequestParam("file") MultipartFile file,
HttpServletRequest request) throws JsonProcessingException { HttpServletRequest request) throws JsonProcessingException {
// 获取文件名
String fileName = file.getOriginalFilename(); String fileName = file.getOriginalFilename();
//判断是否为IE浏览器的文件名IE浏览器下文件名会带有盘符信息
// Check for Unix-style path
int unixSep = fileName.lastIndexOf('/');
// Check for Windows-style path
int winSep = fileName.lastIndexOf('\\');
// Cut off at latest possible point
int pos = (winSep > unixSep ? winSep : unixSep);
if (pos != -1) {
fileName = fileName.substring(pos + 1);
}
// 判断该文件类型是否有上传过,如果上传过则提示不允许再次上传 // 判断该文件类型是否有上传过,如果上传过则提示不允许再次上传
if (existsTypeFile(fileName)) { if (existsTypeFile(fileName)) {
return new ObjectMapper().writeValueAsString(new ReturnResponse<String>(1, "每一种类型只可以上传一个文件,请先删除原有文件再次上传", null)); return new ObjectMapper().writeValueAsString(new ReturnResponse<String>(1, "每一种类型只可以上传一个文件,请先删除原有文件再次上传", null));

View File

@@ -1,10 +1,15 @@
package cn.keking.web.controller; package cn.keking.web.controller;
import cn.keking.config.ConfigConstants;
import cn.keking.model.FileAttribute;
import cn.keking.service.FilePreview; import cn.keking.service.FilePreview;
import cn.keking.service.FilePreviewFactory; import cn.keking.service.FilePreviewFactory;
import cn.keking.service.cache.CacheService; import cn.keking.service.cache.CacheService;
import cn.keking.utils.FileUtils;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; import org.springframework.ui.Model;
@@ -26,12 +31,19 @@ import java.util.List;
@Controller @Controller
public class OnlinePreviewController { public class OnlinePreviewController {
private static final Logger LOGGER = LoggerFactory.getLogger(OnlinePreviewController.class);
@Autowired @Autowired
FilePreviewFactory previewFactory; FilePreviewFactory previewFactory;
@Autowired @Autowired
CacheService cacheService; CacheService cacheService;
@Autowired
private FileUtils fileUtils;
private String fileDir = ConfigConstants.getFileDir();
/** /**
* @param url * @param url
* @param model * @param model
@@ -39,11 +51,12 @@ public class OnlinePreviewController {
*/ */
@RequestMapping(value = "onlinePreview", method = RequestMethod.GET) @RequestMapping(value = "onlinePreview", method = RequestMethod.GET)
public String onlinePreview(String url, Model model, HttpServletRequest req) { public String onlinePreview(String url, Model model, HttpServletRequest req) {
FileAttribute fileAttribute = fileUtils.getFileAttribute(url);
req.setAttribute("fileKey", req.getParameter("fileKey")); req.setAttribute("fileKey", req.getParameter("fileKey"));
model.addAttribute("officePreviewType", req.getParameter("officePreviewType")); model.addAttribute("officePreviewType", req.getParameter("officePreviewType"));
model.addAttribute("originUrl",req.getRequestURL().toString()); model.addAttribute("originUrl", req.getRequestURL().toString());
FilePreview filePreview = previewFactory.get(url); FilePreview filePreview = previewFactory.get(fileAttribute);
return filePreview.filePreviewHandle(url, model); return filePreview.filePreviewHandle(url, model, fileAttribute);
} }
/** /**
@@ -105,7 +118,7 @@ public class OnlinePreviewController {
resp.getOutputStream().write(bs, 0, len); resp.getOutputStream().write(bs, 0, len);
} }
} catch (IOException | URISyntaxException e) { } catch (IOException | URISyntaxException e) {
e.printStackTrace(); LOGGER.error("下载pdf文件失败", e);
} finally { } finally {
if (inputStream != null) { if (inputStream != null) {
IOUtils.closeQuietly(inputStream); IOUtils.closeQuietly(inputStream);

View File

@@ -1 +0,0 @@
app.id=file-preview

View File

@@ -1,15 +1,16 @@
function isInSight(el) { function isInSight(el) {
const bound = el.getBoundingClientRect(); var bound = el.getBoundingClientRect();
const clientHeight = window.innerHeight; var clientHeight = window.innerHeight;
//只考虑向下滚动加载 //只考虑向下滚动加载
//const clientWidth=window.innerWeight; //const clientWidth=window.innerWeight;
return bound.top <= clientHeight + 100; return bound.top <= clientHeight + 100;
} }
let index = 0; var index = 0;
function checkImgs() { function checkImgs() {
const imgs = document.querySelectorAll('.my-photo'); var imgs = document.querySelectorAll('.my-photo');
for (let i = index; i < imgs.length; i++) { for (var i = index; i < imgs.length; i++) {
if (isInSight(imgs[i])) { if (isInSight(imgs[i])) {
loadImg(imgs[i]); loadImg(imgs[i]);
index = i; index = i;
@@ -18,24 +19,47 @@ function checkImgs() {
} }
function loadImg(el) { function loadImg(el) {
const source = el.dataset.src; var source = el.getAttribute("data-src");
el.src = source; el.src = source;
} }
// var mustRun = 500
// function throttle(fn, mustRun) {
// var timer = null;
// var previous = null;
// return function() {
// var now = new Date();
// var context = this;
// var args = arguments;
// if (!previous) {
// previous = now;
// }
// var remaining = now - previous;
// if (mustRun && remaining >= mustRun) {
// fn.apply(context, args);
// previous = now;
// }
// }
// }
function throttle(fn, mustRun = 500) {
const timer = null; function throttle(fn) {
let previous = null; var timer = null;
return function() { var previous = null;
const now = new Date(); return function () {
const context = this; var now = new Date();
const args = arguments; var context = this;
var args = arguments;
if (!previous) { if (!previous) {
previous = now; previous = now;
} }
const remaining = now - previous; var remaining = now - previous;
if (mustRun && remaining >= mustRun) { setTimeout(refresh(fn, remaining, context, args, previous, now));
}
}
function refresh(fn, remaining, context, args, previous, now) {
if (remaining >= 500) {
fn.apply(context, args); fn.apply(context, args);
previous = now; previous = now;
} }
}
} }

View File

@@ -27,17 +27,9 @@ See https://github.com/adobe-type-tools/cmap-resources
<meta name="google" content="notranslate"> <meta name="google" content="notranslate">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>PDF.js viewer</title> <title>PDF.js viewer</title>
<link rel="stylesheet" href="viewer.css"> <link rel="stylesheet" href="viewer.css">
<link rel="resource" type="application/l10n" href="locale/locale.properties">
<script src="../build/pdf.js"></script>
<!-- This snippet is used in production (included from viewer.html) -->
<link rel="resource" type="application/l10n" href="locale/locale.properties">
<script src="../build/pdf.js"></script>
<script src="../../config.js"></script>
<script src="viewer.js"></script> <script src="viewer.js"></script>
</head> </head>

View File

@@ -1897,7 +1897,7 @@ var validateFileURL = void 0;
} }
var fileOrigin = new URL(file, window.location.href).origin; var fileOrigin = new URL(file, window.location.href).origin;
if (fileOrigin !== viewerOrigin) { if (fileOrigin !== viewerOrigin) {
return '/getCorsFile?urlPath=' + file; return '/getCorsFile?urlPath=' + encodeURIComponent(file);
} }
} catch (ex) { } catch (ex) {
var message = ex && ex.message; var message = ex && ex.message;

View File

@@ -68,7 +68,7 @@
fulls += ",resizable"; // 对于不支持screen属性的浏览器可以手工进行最大化。 manually fulls += ",resizable"; // 对于不支持screen属性的浏览器可以手工进行最大化。 manually
} }
window.open("onlinePreview?url=" window.open("onlinePreview?url="
+ encodeURIComponent("${baseUrl}" + treeNode.fileName)+"&fileKey="+treeNode.fileKey, "_blank",fulls); + encodeURIComponent("${baseUrl}" + treeNode.fileName)+"&fileKey="+ encodeURIComponent(treeNode.fileKey), "_blank",fulls);
} }
} }
} }

View File

@@ -2,11 +2,11 @@
<html lang="en"> <html lang="en">
<head> <head>
<title>图片预览图</title> <title>kkFileView演示首页</title>
<link rel="stylesheet" href="css/viewer.min.css"> <link rel="stylesheet" href="css/viewer.min.css">
<link rel="stylesheet" href="css/loading.css"> <link rel="stylesheet" href="css/loading.css">
<link rel="stylesheet" href="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/css/bootstrap.min.css"> <link rel="stylesheet" href="//cdn.static.runoob.com/libs/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.11.1/bootstrap-table.css" /> <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.11.1/bootstrap-table.css" />
<style type="text/css"> <style type="text/css">
</style> </style>
</head> </head>
@@ -29,22 +29,15 @@
如果你的项目需要接入文件预览项目达到对docx、excel、ppt、jpg等文件的预览效果那么通过在你的项目中加入下面的代码就可以 如果你的项目需要接入文件预览项目达到对docx、excel、ppt、jpg等文件的预览效果那么通过在你的项目中加入下面的代码就可以
成功实现: 成功实现:
<pre style="background-color: #2f332a;color: #cccccc"> <pre style="background-color: #2f332a;color: #cccccc">
$scope.openWin = function (fileUrl) { var url = 'http://127.0.0.1:8080/file/test.txt'; //要预览文件的访问地址
var url = configuration.previewUrl + encodeURIComponent(fileUrl); window.open('http://127.0.0.1:8012/onlinePreview?url='+encodeURIComponent(url));
var winHeight = window.document.documentElement.clientHeight-10;
$window.open(url, "_blank", "height=" + winHeight
+ ",top=80,left=80,toolbar=no, menubar=no, scrollbars=yes, resizable=yes");
};
</pre> </pre>
</div> </div>
<div> <div>
新增多图片同时预览功能,接口如下: 新增多图片同时预览功能,接口如下:
<pre style="background-color: #2f332a;color: #cccccc"> <pre style="background-color: #2f332a;color: #cccccc">
var fileUrl =url1+"|"+"url2";//多文件使用“|”字符隔开 var fileUrl =url1+"|"+"url2";//多文件使用“|”字符隔开
var url = "http://localhost:8012/picturesPreview?urls" + encodeURIComponent(fileUrl); window.open('http://127.0.0.1:8012/picturesPreview?urls='+encodeURIComponent(fileUrl));
var winHeight = window.document.documentElement.clientHeight-10;
$window.open(url, "_blank", "height=" + winHeight
+ ",top=80,left=80,toolbar=no, menubar=no, scrollbars=yes, resizable=yes");
</pre> </pre>
</div> </div>
</div> </div>
@@ -86,6 +79,21 @@
<div id="collapseThree" class="panel-collapse collapse in"> <div id="collapseThree" class="panel-collapse collapse in">
<div class="panel-body"> <div class="panel-body">
<div> <div>
2019年06月18日 <br>
1. 支持自动清理缓存及预览文件<br>
2. 支持http/https下载流url文件预览<br>
3. 支持FTP url文件预览<br>
4. 加入Docker构建<br><br>
2019年04月08日 <br>
1. 缓存及队列实现抽象提供JDK和REDIS两种实现(REDIS成为可选依赖)<br>
2. 打包方式提供zip和tar.gz包并提供一键启动脚本<br><br>
2018年01月19日 <br>
1. 大文件入队提前处理<br>
1. 新增addTask文件转换入队接口<br>
1. 采用redis队列支持kkFIleView接口和异构系统入队两种方式<br><br>
2018年01月15日 <br> 2018年01月15日 <br>
1.首页新增社会化评论框<br><br> 1.首页新增社会化评论框<br><br>
@@ -100,7 +108,7 @@
4.引入pdf.js预览doc等文件支持doc标题生成pdf预览菜单支持手机端预览<br><br> 4.引入pdf.js预览doc等文件支持doc标题生成pdf预览菜单支持手机端预览<br><br>
2017年12月12日<br> 2017年12月12日<br>
1.项目osc开源:<a href="https://gitee.com/kekingcn/file-online-preview" target="_blank">https://gitee.com/kekingcn/file-online-preview</a><br> 1.项目gitee开源:<a href="https://gitee.com/kekingcn/file-online-preview" target="_blank">https://gitee.com/kekingcn/file-online-preview</a><br>
2.项目github开源:<a href="https://github.com/kekingcn/kkFileView" target="_blank">https://github.com/kekingcn/kkFileView</a> 2.项目github开源:<a href="https://github.com/kekingcn/kkFileView" target="_blank">https://github.com/kekingcn/kkFileView</a>
</div> </div>
</div> </div>
@@ -109,7 +117,7 @@
<div style="width: 80%"> <div style="width: 80%">
<!-- 多说评论框 start --> <!-- 多说评论框 start -->
<div id="SOHUCS" sid="kkfileView"></div> <div id="SOHUCS" sid="kkfileView"></div>
<script charset="utf-8" type="text/javascript" src="https://changyan.sohu.com/upload/changyan.js" ></script> <script charset="utf-8" type="text/javascript" src="//changyan.sohu.com/upload/changyan.js" ></script>
<script type="text/javascript"> <script type="text/javascript">
window.changyan.api.config({ window.changyan.api.config({
appid: 'cytx6wU4N', appid: 'cytx6wU4N',
@@ -146,9 +154,9 @@
</div> </div>
</div> </div>
<script src="js/jquery-3.0.0.min.js" type="text/javascript"></script> <script src="js/jquery-3.0.0.min.js" type="text/javascript"></script>
<script src="https://cdn.bootcss.com/jquery.form/3.09/jquery.form.min.js" type="text/javascript"></script> <script src="//cdn.bootcss.com/jquery.form/3.09/jquery.form.min.js" type="text/javascript"></script>
<script src="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/js/bootstrap.min.js"></script> <script src="//cdn.static.runoob.com/libs/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.11.1/bootstrap-table.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.11.1/bootstrap-table.js"></script>
<script> <script>
function deleteFile(fileName) { function deleteFile(fileName) {
$.ajax({ $.ajax({
@@ -157,7 +165,7 @@
// 删除完成刷新table // 删除完成刷新table
if (1 == data.code) { if (1 == data.code) {
alert(data.msg); alert(data.msg);
}else{ } else{
$('#table').bootstrapTable('refresh', {}); $('#table').bootstrapTable('refresh', {});
} }
}, },
@@ -179,9 +187,8 @@
}).on('pre-body.bs.table', function (e,data) { }).on('pre-body.bs.table', function (e,data) {
// 每个data添加一列用来操作 // 每个data添加一列用来操作
$(data).each(function (index, item) { $(data).each(function (index, item) {
item.action = "<a class='btn btn-default' target='_blank' href='${baseUrl}onlinePreview?url=" item.action = "<a class='btn btn-default' target='_blank' href='${baseUrl}onlinePreview?url="+ encodeURIComponent('${baseUrl}' + item.fileName ) +"'>预览</a>" +
+ encodeURIComponent('${baseUrl}' + item.fileName ) +"'>预览</a>" + "<a class='btn btn-default' href='javascript:void(0);' onclick='deleteFile(\""+item.fileName+"\")'>删除</a>";
"<a class='btn btn-default' target='_blank' href='javascript:void(0);' onclick='deleteFile(\""+item.fileName+"\")'>删除</a>";
}); });
return data; return data;
}).on('post-body.bs.table', function (e,data) { }).on('post-body.bs.table', function (e,data) {

View File

@@ -25,7 +25,7 @@
</#list> </#list>
</div> </div>
<#--<img src="images/right.png" style="position: fixed; cursor: pointer; top: 40%; right: 60px; z-index: 999;" alt="使用PDF预览" title="使用PDF预览" onclick="changePreviewType('pdf')"/>--> <#--<img src="images/right.png" style="position: fixed; cursor: pointer; top: 40%; right: 60px; z-index: 999;" alt="使用PDF预览" title="使用PDF预览" onclick="changePreviewType('pdf')"/>-->
<span class="fa fa-file-pdf-o fa-5x" style="position: fixed; cursor: pointer; top: 40%; right: 50px; z-index: 999;" title="使用PDF预览" onclick="changePreviewType('pdf')"></span> <span class="fa fa-file-pdf-o fa-4x" style="position: fixed; cursor: pointer; top: 40%; right: 50px; z-index: 999;" title="使用PDF预览" onclick="changePreviewType('pdf')"></span>
<script> <script>
window.onload=checkImgs; window.onload=checkImgs;
window.onscroll = throttle(checkImgs); window.onscroll = throttle(checkImgs);

View File

@@ -20,7 +20,7 @@
<iframe src="" width="100%" frameborder="0"></iframe> <iframe src="" width="100%" frameborder="0"></iframe>
<#-- <img src="images/left.png" style="position: fixed; cursor: pointer; top: 40%; right: 60px; z-index: 999;" alt="使用图片预览" title="使用图片预览" onclick="goForImage()"/>--> <#-- <img src="images/left.png" style="position: fixed; cursor: pointer; top: 40%; right: 60px; z-index: 999;" alt="使用图片预览" title="使用图片预览" onclick="goForImage()"/>-->
<span class="fa fa-file-image-o fa-5x" style="position: fixed; cursor: pointer; top: 40%; right: 50px; z-index: 999;" title="使用图片预览" onclick="goForImage()"></span> <span class="fa fa-file-image-o fa-4x" style="position: fixed; cursor: pointer; top: 40%; right: 50px; z-index: 999;" title="使用图片预览" onclick="goForImage()"></span>
</body> </body>

View File

@@ -5,7 +5,7 @@
<groupId>cn.keking</groupId> <groupId>cn.keking</groupId>
<artifactId>filepreview</artifactId> <artifactId>filepreview</artifactId>
<version>0.0.1-SNAPSHOT</version> <version>2.2.0-SNAPSHOT</version>
<modules> <modules>
<module>jodconverter-core</module> <module>jodconverter-core</module>
<module>jodconverter-web</module> <module>jodconverter-web</module>