mirror of
https://gitee.com/kekingcn/file-online-preview.git
synced 2026-04-28 19:16:43 +00:00
Compare commits
113 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8b33a233dd | ||
|
|
9e2962bb62 | ||
|
|
fc73deb3fd | ||
|
|
40ac4b1eb9 | ||
|
|
3d6da5f5a0 | ||
|
|
7c4fc42247 | ||
|
|
0c2a92080e | ||
|
|
b1fd13bcbb | ||
|
|
cd37ff4b41 | ||
|
|
215e9f0f4a | ||
|
|
26e147b426 | ||
|
|
c7318c2b17 | ||
|
|
c16116c7cd | ||
|
|
1a4748bbec | ||
|
|
c0f7d60213 | ||
|
|
bf83a0847d | ||
|
|
7601d49795 | ||
|
|
1edf4d83f1 | ||
|
|
f620c00785 | ||
|
|
180e7bcb8a | ||
|
|
8a52450629 | ||
|
|
a535ebfe1d | ||
|
|
3e80590a82 | ||
|
|
5196536bb4 | ||
|
|
59ac8effc1 | ||
|
|
9cc0267619 | ||
|
|
a21f35c2b0 | ||
|
|
fde31cb327 | ||
|
|
9c096605bb | ||
|
|
b90e326eec | ||
|
|
66e2acd063 | ||
|
|
44165d655d | ||
|
|
c9a6956b0d | ||
|
|
9288564195 | ||
|
|
9b8e7f812c | ||
|
|
3908f1be7e | ||
|
|
15bd035304 | ||
|
|
e0b1cd76ca | ||
|
|
2144b776b1 | ||
|
|
a8022df1d9 | ||
|
|
a5d92bf905 | ||
|
|
81a18d07c3 | ||
|
|
86e5dcb23b | ||
|
|
1339c09382 | ||
|
|
01e310a6e7 | ||
|
|
a07c962867 | ||
|
|
09b6964c0e | ||
|
|
461030d34f | ||
|
|
c1a7cd8c46 | ||
|
|
5888c56f1d | ||
|
|
0798b8d8a0 | ||
|
|
ae93d48b44 | ||
|
|
506a3ba2b3 | ||
|
|
12f197b623 | ||
|
|
2001b241ee | ||
|
|
7911edec4b | ||
|
|
7ea70bf422 | ||
|
|
b1fdbd26a3 | ||
|
|
fa7241bd4e | ||
|
|
8fdf462c6c | ||
|
|
f7c7411bcf | ||
|
|
845cb2e657 | ||
|
|
a4bfde68bd | ||
|
|
19d1ba6cf9 | ||
|
|
1060bdd00f | ||
|
|
8c2fb2bdee | ||
|
|
0fe75387eb | ||
|
|
fbea49e54f | ||
|
|
41a72798d9 | ||
|
|
03cc185085 | ||
|
|
bfbd8ee25e | ||
|
|
f3f36169ff | ||
|
|
2df88544d3 | ||
|
|
6b744d77c7 | ||
|
|
ba57dedebb | ||
|
|
affd5b3057 | ||
|
|
30c3128995 | ||
|
|
b003a05775 | ||
|
|
98ec3d7dab | ||
|
|
69e23dbb99 | ||
|
|
47bda1023a | ||
|
|
fd538a74af | ||
|
|
300d213a7a | ||
|
|
4c0a70f300 | ||
|
|
8798d344b6 | ||
|
|
63e62ab57b | ||
|
|
9a027674ac | ||
|
|
e4407467dd | ||
|
|
551eeb0390 | ||
|
|
11d6ad1ed3 | ||
|
|
e57db6925c | ||
|
|
87096364d8 | ||
|
|
ad8027a7d0 | ||
|
|
9786fa8275 | ||
|
|
37762cf034 | ||
|
|
a78f1e5f8e | ||
|
|
440b8030e0 | ||
|
|
fb7cdfbef7 | ||
|
|
cf1ee9c631 | ||
|
|
13123f8f9d | ||
|
|
189bc3965d | ||
|
|
0aa7444dba | ||
|
|
628efec6bd | ||
|
|
6d0846a551 | ||
|
|
41d9015023 | ||
|
|
3f40b60c64 | ||
|
|
f244054462 | ||
|
|
37fbc98827 | ||
|
|
795cf3393e | ||
|
|
70323b8ee3 | ||
|
|
67686e99f0 | ||
|
|
90554462dc | ||
|
|
ba3084d698 |
5
.gitattributes
vendored
Normal file
5
.gitattributes
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
*.css linguist-language=java
|
||||||
|
*.less linguist-language=java
|
||||||
|
*.js linguist-language=java
|
||||||
|
*.html linguist-language=java
|
||||||
|
*.* linguist-language=java
|
||||||
19
.gitignore
vendored
19
.gitignore
vendored
@@ -24,17 +24,8 @@ nbdist/
|
|||||||
.nb-gradle/
|
.nb-gradle/
|
||||||
/*.iml
|
/*.iml
|
||||||
|
|
||||||
**/target/
|
### VS Code ###
|
||||||
.classpath
|
.vscode/
|
||||||
.project
|
|
||||||
**/.settings
|
jodconverter-web/src/main/cache/
|
||||||
**/build/
|
jodconverter-web/src/main/file/
|
||||||
**/.externalToolBuilders/
|
|
||||||
*.iml
|
|
||||||
**/.idea/
|
|
||||||
**/disconf
|
|
||||||
**/rpc.properties
|
|
||||||
/producer/tmp
|
|
||||||
/.temfile
|
|
||||||
.temfile
|
|
||||||
convertedFile/
|
|
||||||
|
|||||||
29
Dockerfile
Normal file
29
Dockerfile
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
FROM ubuntu:20.04
|
||||||
|
MAINTAINER chenjh "842761733@qq.com"
|
||||||
|
ADD jodconverter-web/target/kkFileView-*.tar.gz /opt/
|
||||||
|
COPY fonts/* /usr/share/fonts/chienes/
|
||||||
|
RUN echo "deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse\ndeb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse\ndeb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse\ndeb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse\ndeb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse\ndeb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse\ndeb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse\ndeb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse\ndeb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse\ndeb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse" > /etc/apt/sources.list &&\
|
||||||
|
apt-get clean && apt-get update &&\
|
||||||
|
apt-get install -y locales && apt-get install -y language-pack-zh-hans &&\
|
||||||
|
localedef -i zh_CN -c -f UTF-8 -A /usr/share/locale/locale.alias zh_CN.UTF-8 && locale-gen zh_CN.UTF-8 &&\
|
||||||
|
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 &&\
|
||||||
|
cd /tmp &&\
|
||||||
|
wget https://kkfileview.keking.cn/server-jre-8u251-linux-x64.tar.gz &&\
|
||||||
|
wget https://kkfileview.keking.cn/Apache_OpenOffice_4.1.6_Linux_x86-64_install-deb_zh-CN.tar.gz -cO openoffice_deb.tar.gz &&\
|
||||||
|
tar -zxf /tmp/server-jre-8u251-linux-x64.tar.gz && mv /tmp/jdk1.8.0_251 /usr/local/ &&\
|
||||||
|
tar -zxf /tmp/openoffice_deb.tar.gz && cd /tmp/zh-CN/DEBS &&\
|
||||||
|
dpkg -i *.deb && dpkg -i desktop-integration/openoffice4.1-debian-menus_4.1.6-9790_all.deb &&\
|
||||||
|
rm -rf /tmp/* && rm -rf /var/lib/apt/lists/* &&\
|
||||||
|
cd /usr/share/fonts/chienes &&\
|
||||||
|
mkfontscale &&\
|
||||||
|
mkfontdir &&\
|
||||||
|
fc-cache -fv
|
||||||
|
ENV JAVA_HOME /usr/local/jdk1.8.0_251
|
||||||
|
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
|
||||||
|
ENV PATH $PATH:$JAVA_HOME/bin
|
||||||
|
ENV LANG zh_CN.UTF-8
|
||||||
|
ENV LC_ALL zh_CN.UTF-8
|
||||||
|
ENV KKFILEVIEW_BIN_FOLDER /opt/kkFileView-2.2.1/bin
|
||||||
|
ENTRYPOINT ["java","-Dfile.encoding=UTF-8","-Dsun.java2d.cmm=sun.java2d.cmm.kcms.KcmsServiceProvider","-Dspring.config.location=/opt/kkFileView-2.2.1/config/application.properties","-jar","/opt/kkFileView-2.2.1/bin/kkFileView-2.2.1.jar"]
|
||||||
104
README.en.md
104
README.en.md
@@ -16,14 +16,19 @@ special thanks to the supports of @唐老大 and the contributions of @端木详
|
|||||||
- REST API
|
- REST API
|
||||||
- Abstract file preview interface so that it is easy to extend more file extensions and develop this project on your own
|
- Abstract file preview interface so that it is easy to extend more file extensions and develop this project on your own
|
||||||
|
|
||||||
|
### Official website and DOCS
|
||||||
|
|
||||||
|
URL:[https://kkfileview.keking.cn](https://kkfileview.keking.cn)
|
||||||
|
|
||||||
### Live demo
|
### Live demo
|
||||||
> Please treat public service kindly, or this would stop at any time.
|
> Please treat public service kindly, or this would stop at any time.
|
||||||
|
|
||||||
URL:http://file.keking.cn/
|
URL:[https://file.keking.cn](https://file.keking.cn)
|
||||||
|
|
||||||
### Documentation
|
### Documentation
|
||||||
|
1. Full wiki document:https://gitee.com/kekingcn/file-online-preview/wikis/pages
|
||||||
1. 中文文档:https://gitee.com/kekingcn/file-online-preview/blob/master/README.md
|
1. 中文文档:https://gitee.com/kekingcn/file-online-preview/blob/master/README.md
|
||||||
1. English document:https://github.com/kekingcn/kkFileView/blob/master/README.en.md
|
1. English document:https://gitee.com/kekingcn/file-online-preview/blob/master/README.en.md
|
||||||
|
|
||||||
### Contact us && Join us
|
### Contact us && Join us
|
||||||
> We will answer everyone's questions in use of this project.
|
> We will answer everyone's questions in use of this project.
|
||||||
@@ -34,20 +39,62 @@ Cherish life away from ineffective communication.
|
|||||||
QQ group:613025121
|
QQ group:613025121
|
||||||
|
|
||||||
### Pictures for some samples
|
### Pictures for some samples
|
||||||
> Excel
|
#### 1. Text Preview
|
||||||
|
It supports preview of all types of text documents. Because there are too many types of text documents, it is impossible to enumerate them. The default open types are as follows: txt,html,htm,asp,jsp,xml,json,properties,md,gitignore,log,java,py,c,cpp,sql,sh,bat,m,bas,prg,cmd
|
||||||
|
The text preview effect is as follows
|
||||||
|

|
||||||
|
|
||||||

|
#### 2. Picture preview
|
||||||
> doc
|
Support jpg, jpeg, png, gif and other picture previews (flip, zoom, mirror). The preview effect is as follows
|
||||||
|

|
||||||
|
|
||||||

|
#### 3. Word document preview
|
||||||
|
Doc and docx document previews are supported. There are two modes of word previews: one is that each page of word is converted to picture previews, the other is that the whole word document is converted to PDF, and then previews PDF. The applicable scenarios of the two modes are as follows
|
||||||
|
* Picture preview modes: the word file is large, and the whole PDF loaded in the foreground is too slow
|
||||||
|
* Pdf Preview modes: intranet access, loading PDF fast
|
||||||
|
The preview effect of picture preview mode is as follows
|
||||||
|

|
||||||
|
The preview effect of PDF preview mode is as follows
|
||||||
|

|
||||||
|
|
||||||
> zip,rar
|
#### 4. PPT document preview
|
||||||
|
ppt and pptx document preview are supported. Like word documents, there are two preview modes
|
||||||
|
The preview effect of picture preview mode is as follows
|
||||||
|

|
||||||
|
The preview effect of PDF preview mode is as follows
|
||||||
|

|
||||||
|
|
||||||

|
#### 5. PDF document preview
|
||||||
|
Pdf document preview is supported. Like word document, there are two preview modes
|
||||||
|
The preview effect of picture preview mode is as follows
|
||||||
|

|
||||||
|
The preview effect of PDF preview mode is as follows
|
||||||
|

|
||||||
|
|
||||||
> png,jpeg,jpg,etc., support for zooming with mouse scroll, rotation, inversion,etc.
|
#### 6. EXCEL document preview
|
||||||
|
Support XLS, xlsx document preview, the preview effect is as follows
|
||||||
|

|
||||||
|
|
||||||

|
#### 7. Compressed file Preview
|
||||||
|
Support zip, rar, jar, tar, gzip and other compressed packages. The preview effect is as follows
|
||||||
|

|
||||||
|
Click the file name in the compressed package to preview the file directly. The preview effect is as follows
|
||||||
|

|
||||||
|
|
||||||
|
#### 8. Multimedia file Preview
|
||||||
|
Theoretically, all video and audio files are supported. Since all file formats cannot be enumerated, the default open type is as follows
|
||||||
|
mp3,wav,mp4,flv
|
||||||
|
The video preview effect is as follows
|
||||||
|

|
||||||
|
The audio preview effect is as follows
|
||||||
|

|
||||||
|
|
||||||
|
#### 9. CAD document preview
|
||||||
|
CAD DWG document preview is supported. Like word document, there are two preview modes
|
||||||
|
The preview effect of Picture preview mode is as follows
|
||||||
|

|
||||||
|
The preview effect of PDF preview mode is as follows
|
||||||
|

|
||||||
Considering space issues, the pictures of other types of documents will not be shown here.You can deploy it by yourself if you are interested in our project.There is a way to deploy it as below.
|
Considering space issues, the pictures of other types of documents will not be shown here.You can deploy it by yourself if you are interested in our project.There is a way to deploy it as below.
|
||||||
|
|
||||||
### Quick Start
|
### Quick Start
|
||||||
@@ -58,25 +105,38 @@ 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 step:configure redis address and OpenOffice directory,such as
|
2. Third step:Run 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 step:Run 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.
|
||||||

|

|
||||||
|
|
||||||
### Changelog
|
### Changelog
|
||||||
|
> May 20th 2020 :
|
||||||
|
1. Support for global watermark and dynamic change of watermark content through parameters
|
||||||
|
2. Support for CAD file Preview
|
||||||
|
3. Add configuration item base.url, support using nginx reverse proxy and set context-path
|
||||||
|
4. All configuration items can be read from environment variables, which is convenient for docker image deployment and large-scale use in cluster
|
||||||
|
5. Support the configuration of TrustHost (only the file source from the trust site can be previewed), and protect the preview service from abuse
|
||||||
|
6. Support configuration of customize cache cleanup time (cron expression)
|
||||||
|
7. All recognizable plain text can be previewed directly without downloading, such as .md .java .py, etc
|
||||||
|
8. Support configuration to limit PDF file download after conversion
|
||||||
|
9. Optimize Maven packaging configuration to solve the problem of line break in .sh script
|
||||||
|
10. Place all CDN dependencies on the front end locally for users without external network connection
|
||||||
|
11. Comment Service on home page switched from Sohu ChangYan to gitalk
|
||||||
|
12. Fixed preview exceptions that may be caused by special characters in the URL
|
||||||
|
13. Fixed the addtask exception of the transformation file queue
|
||||||
|
14. Fixed other known issues
|
||||||
|
15. Official website build: [https://kkfileview.keking.cn](https://kkfileview.keking.cn)
|
||||||
|
16. Official docker image repository build: [https://hub.docker.com/r/keking/kkfileview](https://hub.docker.com/r/keking/kkfileview)
|
||||||
|
|
||||||
|
> 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)
|
||||||
|
|||||||
107
README.md
107
README.md
@@ -2,7 +2,7 @@
|
|||||||
此项目为文件文档在线预览项目解决方案,对标业内付费产品有【[永中office](http://dcs.yozosoft.com/)】【[office365](http://www.officeweb365.com/)】【[idocv](https://www.idocv.com/)】等,在取得公司高层同意后以Apache协议开源出来反哺社区,在此特别感谢@唐老大的支持以及@端木详笑的贡献。该项目使用流行的spring boot搭建,易上手和部署,基本支持主流办公文档的在线预览,如doc,docx,Excel,pdf,txt,zip,rar,图片等等
|
此项目为文件文档在线预览项目解决方案,对标业内付费产品有【[永中office](http://dcs.yozosoft.com/)】【[office365](http://www.officeweb365.com/)】【[idocv](https://www.idocv.com/)】等,在取得公司高层同意后以Apache协议开源出来反哺社区,在此特别感谢@唐老大的支持以及@端木详笑的贡献。该项目使用流行的spring boot搭建,易上手和部署,基本支持主流办公文档的在线预览,如doc,docx,Excel,pdf,txt,zip,rar,图片等等
|
||||||
### 项目特性
|
### 项目特性
|
||||||
|
|
||||||
1. 支持office,pdf等办公文档
|
1. 支持office,pdf, cad等办公文档
|
||||||
1. 支持txt,java,php,py,md,js,css等所有纯文本
|
1. 支持txt,java,php,py,md,js,css等所有纯文本
|
||||||
1. 支持zip,rar,jar,tar,gzip等压缩包
|
1. 支持zip,rar,jar,tar,gzip等压缩包
|
||||||
1. 支持jpg,jpeg,png,gif等图片预览(翻转,缩放,镜像)
|
1. 支持jpg,jpeg,png,gif等图片预览(翻转,缩放,镜像)
|
||||||
@@ -11,14 +11,19 @@
|
|||||||
1. 抽象预览服务接口,方便二次开发,非常方便添加其他类型文件预览支持
|
1. 抽象预览服务接口,方便二次开发,非常方便添加其他类型文件预览支持
|
||||||
1. 最最重要Apache协议开源,代码pull下来想干嘛就干嘛
|
1. 最最重要Apache协议开源,代码pull下来想干嘛就干嘛
|
||||||
|
|
||||||
|
### 官网及文档
|
||||||
|
|
||||||
|
地址:[https://kkfileview.keking.cn](https://kkfileview.keking.cn)
|
||||||
|
|
||||||
### 在线体验
|
### 在线体验
|
||||||
> 请善待公共服务,会不定时停用
|
> 请善待公共服务,会不定时停用
|
||||||
|
|
||||||
地址:http://file.keking.cn/
|
地址:[https://file.keking.cn](https://file.keking.cn)
|
||||||
|
|
||||||
### 项目文档(Project documentation)
|
### 项目文档(Project documentation)
|
||||||
|
1. 详细wiki文档:https://gitee.com/kekingcn/file-online-preview/wikis/pages
|
||||||
1. 中文文档:https://gitee.com/kekingcn/file-online-preview/blob/master/README.md
|
1. 中文文档:https://gitee.com/kekingcn/file-online-preview/blob/master/README.md
|
||||||
1. English document:https://github.com/kekingcn/kkFileView/blob/master/README.en.md
|
1. English document:https://gitee.com/kekingcn/file-online-preview/blob/master/README.en.md
|
||||||
|
|
||||||
### 联系我们,加入组织
|
### 联系我们,加入组织
|
||||||
> 我们会用心回答解决大家在项目使用中的问题,也请大家在提问前至少Google或baidu过,珍爱生命远离无效的交流沟通
|
> 我们会用心回答解决大家在项目使用中的问题,也请大家在提问前至少Google或baidu过,珍爱生命远离无效的交流沟通
|
||||||
@@ -27,20 +32,62 @@
|
|||||||
QQ群号:613025121
|
QQ群号:613025121
|
||||||
|
|
||||||
### 文档预览效果
|
### 文档预览效果
|
||||||
> Excel预览效果
|
#### 1. 文本预览
|
||||||
|
支持所有类型的文本文档预览, 由于文本文档类型过多,无法全部枚举,默认开启的类型如下 txt,html,htm,asp,jsp,xml,json,properties,md,gitignore,log,java,py,c,cpp,sql,sh,bat,m,bas,prg,cmd
|
||||||
|
文本预览效果如下
|
||||||
|

|
||||||
|
|
||||||

|
#### 2. 图片预览
|
||||||
> doc预览效果
|
支持jpg,jpeg,png,gif等图片预览(翻转,缩放,镜像),预览效果如下
|
||||||
|

|
||||||
|
|
||||||

|
#### 3. word文档预览
|
||||||
|
支持doc,docx文档预览,word预览有两种模式:一种是每页word转为图片预览,另一种是整个word文档转成pdf,再预览pdf。两种模式的适用场景如下
|
||||||
|
* 图片预览:word文件大,前台加载整个pdf过慢
|
||||||
|
* pdf预览:内网访问,加载pdf快
|
||||||
|
图片预览模式预览效果如下
|
||||||
|

|
||||||
|
pdf预览模式预览效果如下
|
||||||
|

|
||||||
|
|
||||||
> zip,rar压缩预览效果
|
#### 4. ppt文档预览
|
||||||
|
支持ppt,pptx文档预览,和word文档一样,有两种预览模式
|
||||||
|
图片预览模式预览效果如下
|
||||||
|

|
||||||
|
pdf预览模式预览效果如下
|
||||||
|

|
||||||
|
|
||||||

|
#### 5. pdf文档预览
|
||||||
|
支持pdf文档预览,和word文档一样,有两种预览模式
|
||||||
|
图片预览模式预览效果如下
|
||||||
|

|
||||||
|
pdf预览模式预览效果如下
|
||||||
|

|
||||||
|
|
||||||
> png,jpeg,jpg等图片预览效果,支持滚轮缩放,旋转,倒置等
|
#### 6. excel文档预览
|
||||||
|
支持xls,xlsx文档预览,预览效果如下
|
||||||
|

|
||||||
|
|
||||||

|
#### 7. 压缩文件预览
|
||||||
|
支持zip,rar,jar,tar,gzip等压缩包,预览效果如下
|
||||||
|

|
||||||
|
可点击压缩包中的文件名,直接预览文件,预览效果如下
|
||||||
|

|
||||||
|
|
||||||
|
#### 8. 多媒体文件预览
|
||||||
|
理论上支持所有的视频、音频文件,由于无法枚举所有文件格式,默认开启的类型如下
|
||||||
|
mp3,wav,mp4,flv
|
||||||
|
视频预览效果如下
|
||||||
|

|
||||||
|
音频预览效果如下
|
||||||
|

|
||||||
|
|
||||||
|
#### 9. CAD文档预览
|
||||||
|
支持CAD dwg文档预览,和word文档一样,有两种预览模式
|
||||||
|
图片预览模式预览效果如下
|
||||||
|

|
||||||
|
pdf预览模式预览效果如下
|
||||||
|

|
||||||
考虑说明篇幅原因,就不贴其他格式文件的预览效果了,感兴趣的可以参考下面的实例搭建下
|
考虑说明篇幅原因,就不贴其他格式文件的预览效果了,感兴趣的可以参考下面的实例搭建下
|
||||||
|
|
||||||
### 快速开始
|
### 快速开始
|
||||||
@@ -51,26 +98,40 @@ 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/
|
|
||||||
会看到如下界面,代表服务启动成功
|
会看到如下界面,代表服务启动成功
|
||||||

|

|
||||||
|
|
||||||
### 历史更新记录
|
### 历史更新记录
|
||||||
|
|
||||||
|
> 2020年05月20日 :
|
||||||
|
1. 新增支持全局水印,并支持通过参数动态改变水印内容
|
||||||
|
2. 新增支持CAD文件预览
|
||||||
|
3. 新增base.url配置,支持使用nginx反向代理和使用context-path
|
||||||
|
4. 支持所有配置项支持从环境变量里读取,方便Docker镜像部署和集群中大规模使用
|
||||||
|
5. 支持配置限信任站点(只能预览来自信任点的文件源),保护预览服务不被滥用
|
||||||
|
6. 支持配置自定义缓存清理时间(cron表达式)
|
||||||
|
7. 全部能识别的纯文本直接预览,不用再转跳下载,如.md .java .py等
|
||||||
|
8. 支持配置限制转换后的PDF文件下载
|
||||||
|
9. 优化maven打包配置,解决 .sh 脚本可能出现换行符问题
|
||||||
|
10. 将前端所有CDN依赖放到本地,方便没有外网连接的用户使用
|
||||||
|
11. 首页评论服务由搜狐畅言切换到Gitalk
|
||||||
|
12. 修复url中包含特殊字符可能会引起的预览异常
|
||||||
|
13. 修复转换文件队列addTask异常
|
||||||
|
14. 修复其他已经问题
|
||||||
|
15. 官网建设:[https://kkfileview.keking.cn](https://kkfileview.keking.cn)
|
||||||
|
16. 官方Docker镜像仓库建设:[https://hub.docker.com/r/keking/kkfileview](https://hub.docker.com/r/keking/kkfileview)
|
||||||
|
|
||||||
|
> 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
0
fonts/.gitkeep
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
jodconverter-web/lib/aspose-cad-19.9.jar
Normal file
BIN
jodconverter-web/lib/aspose-cad-19.9.jar
Normal file
Binary file not shown.
@@ -12,16 +12,13 @@
|
|||||||
|
|
||||||
<groupId>cn.keking</groupId>
|
<groupId>cn.keking</groupId>
|
||||||
<artifactId>kkFileView</artifactId>
|
<artifactId>kkFileView</artifactId>
|
||||||
<version>2.0</version>
|
<version>2.2.1</version>
|
||||||
|
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
<ufile.sdk.verison>1.0-SNAPSHOT</ufile.sdk.verison>
|
|
||||||
<logging.path>${basedir}/target/classes/logs</logging.path>
|
|
||||||
<appName>file-preview</appName>
|
|
||||||
</properties>
|
</properties>
|
||||||
<repositories>
|
<repositories>
|
||||||
<repository>
|
<repository>
|
||||||
@@ -60,6 +57,11 @@
|
|||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-lang3</artifactId>
|
||||||
|
<version>3.7</version>
|
||||||
|
</dependency>
|
||||||
<!-- REDISSON -->
|
<!-- REDISSON -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.redisson</groupId>
|
<groupId>org.redisson</groupId>
|
||||||
@@ -106,7 +108,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-compress</artifactId>
|
<artifactId>commons-compress</artifactId>
|
||||||
<version>1.18</version>
|
<version>1.19</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- 解压(rar)-->
|
<!-- 解压(rar)-->
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -114,6 +116,12 @@
|
|||||||
<artifactId>junrar</artifactId>
|
<artifactId>junrar</artifactId>
|
||||||
<version>4.0.0</version>
|
<version>4.0.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- 解压(7z)-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.tukaani</groupId>
|
||||||
|
<artifactId>xz</artifactId>
|
||||||
|
<version>1.8</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.sourceforge.jchardet</groupId>
|
<groupId>net.sourceforge.jchardet</groupId>
|
||||||
<artifactId>jchardet</artifactId>
|
<artifactId>jchardet</artifactId>
|
||||||
@@ -141,10 +149,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>
|
||||||
@@ -171,6 +185,13 @@
|
|||||||
<artifactId>pdfbox-tools</artifactId>
|
<artifactId>pdfbox-tools</artifactId>
|
||||||
<version>2.0.15</version>
|
<version>2.0.15</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.aspose</groupId>
|
||||||
|
<artifactId>aspose-cad</artifactId>
|
||||||
|
<version>19.9</version>
|
||||||
|
<scope>system</scope>
|
||||||
|
<systemPath>${basedir}/lib/aspose-cad-19.9.jar</systemPath>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<build>
|
<build>
|
||||||
<resources>
|
<resources>
|
||||||
@@ -179,26 +200,30 @@
|
|||||||
<includes>
|
<includes>
|
||||||
<include>**/*</include>
|
<include>**/*</include>
|
||||||
</includes>
|
</includes>
|
||||||
<filtering>true</filtering>
|
<filtering>false</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>
|
||||||
|
<filtering>true</filtering>
|
||||||
</resource>
|
</resource>
|
||||||
</resources>
|
</resources>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<includeSystemScope>true</includeSystemScope>
|
||||||
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<artifactId>maven-assembly-plugin</artifactId>
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
<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>
|
||||||
|
|||||||
@@ -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>
|
||||||
@@ -2,8 +2,10 @@
|
|||||||
cd /tmp
|
cd /tmp
|
||||||
|
|
||||||
install_redhat() {
|
install_redhat() {
|
||||||
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
|
wget https://kkfileview.keking.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
|
||||||
if [ $? -eq 0 ];then
|
if [ $? -eq 0 ];then
|
||||||
|
yum install -y libXext.x86_64
|
||||||
|
yum groupinstall -y "X Window System"
|
||||||
rpm -Uvih *.rpm
|
rpm -Uvih *.rpm
|
||||||
echo 'install desktop service ...'
|
echo 'install desktop service ...'
|
||||||
rpm -Uvih desktop-integration/openoffice4.1.6-redhat-menus-4.1.6-9790.noarch.rpm
|
rpm -Uvih desktop-integration/openoffice4.1.6-redhat-menus-4.1.6-9790.noarch.rpm
|
||||||
@@ -14,9 +16,13 @@ install_redhat() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
install_ubuntu() {
|
install_ubuntu() {
|
||||||
wget https://iweb.dl.sourceforge.net/project/openofficeorg.mirror/4.1.6/binaries/zh-CN/Apache_OpenOffice_4.1.6_Linux_x86-64_install-deb_zh-CN.tar.gz -cO openoffice_deb.tar.gz && tar zxf /tmp/openoffice_deb.tar.gz && cd /tmp/zh-CN/DEBS
|
wget https://kkfileview.keking.cn/Apache_OpenOffice_4.1.6_Linux_x86-64_install-deb_zh-CN.tar.gz -cO openoffice_deb.tar.gz && tar zxf /tmp/openoffice_deb.tar.gz && cd /tmp/zh-CN/DEBS
|
||||||
echo $?
|
echo $?
|
||||||
if [ $? -eq 0 ];then
|
if [ $? -eq 0 ];then
|
||||||
|
apt-get install -y libxrender1
|
||||||
|
apt-get install -y libxt6
|
||||||
|
apt-get install -y libxext-dev
|
||||||
|
apt-get install -y libfreetype6-dev
|
||||||
dpkg -i *.deb
|
dpkg -i *.deb
|
||||||
echo 'install desktop service ...'
|
echo 'install desktop service ...'
|
||||||
dpkg -i desktop-integration/openoffice4.1-debian-menus_4.1.6-9790_all.deb
|
dpkg -i desktop-integration/openoffice4.1-debian-menus_4.1.6-9790_all.deb
|
||||||
2
jodconverter-web/src/main/bin/showlog.sh
Normal file
2
jodconverter-web/src/main/bin/showlog.sh
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
tail -fn 300 ../log/kkFileView.log
|
||||||
@@ -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}'`
|
||||||
|
|||||||
@@ -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.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.1.jar -> ..\log\kkFileView.log
|
||||||
@@ -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.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.1.jar > ../log/kkFileView.log 2>&1 &
|
||||||
|
|||||||
@@ -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
|
|
||||||
88
jodconverter-web/src/main/config/application.properties
Normal file
88
jodconverter-web/src/main/config/application.properties
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
#######################################不可动态配置,需要重启生效#######################################
|
||||||
|
server.port = ${KK_SERVER_PORT:8012}
|
||||||
|
server.context-path = ${KK_CONTEXT_PATH:/}
|
||||||
|
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=500MB
|
||||||
|
spring.http.multipart.max-file-size=500MB
|
||||||
|
|
||||||
|
#文件资源路径(默认为打包根路径下的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:jdk}
|
||||||
|
#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}
|
||||||
|
|
||||||
|
#信任站点,多个用','隔开,设置了之后,会限制只能预览来自信任站点列表的文件,默认不限制
|
||||||
|
#trust.host = file.keking.cn,kkfileview.keking.cn
|
||||||
|
trust.host = ${KK_TRUST_HOST:default}
|
||||||
|
|
||||||
|
#是否启用缓存
|
||||||
|
cache.enabled = ${KK_CACHE_ENABLED:true}
|
||||||
|
|
||||||
|
#文本类型,默认如下,可自定义添加
|
||||||
|
simText = ${KK_SIMTEXT:txt,html,htm,asp,jsp,xml,json,properties,md,gitignore,log,java,py,c,cpp,sql,sh,bat,m,bas,prg,cmd}
|
||||||
|
#多媒体类型,默认如下,可自定义添加
|
||||||
|
media = ${KK_MEDIA:mp3,wav,mp4,flv}
|
||||||
|
#office类型文档(word ppt)样式,默认为图片(image),可配置为pdf(预览时也有按钮切换)
|
||||||
|
office.preview.type = ${KK_OFFICE_PREVIEW_TYPE:image}
|
||||||
|
#是否禁止下载转换生成的pdf文件
|
||||||
|
pdf.download.disable = ${KK_PDF_DOWNLOAD_DISABLE:true}
|
||||||
|
|
||||||
|
#预览源为FTP时 FTP用户名,可在ftp url后面加参数ftp.username=ftpuser指定,不指定默认用配置的
|
||||||
|
ftp.username = ${KK_FTP_USERNAME:ftpuser}
|
||||||
|
#预览源为FTP时 FTP密码,可在ftp url后面加参数ftp.password=123456指定,不指定默认用配置的
|
||||||
|
ftp.password = ${KK_FTP_PASSWORD:123456}
|
||||||
|
#预览源为FTP时, FTP连接默认ControlEncoding(根据FTP服务器操作系统选择,Linux一般为UTF-8,Windows一般为GBK),可在ftp url后面加参数ftp.control.encoding=UTF-8指定,不指定默认用配置的
|
||||||
|
ftp.control.encoding = ${KK_FTP_CONTROL_ENCODING:UTF-8}
|
||||||
|
|
||||||
|
#水印内容
|
||||||
|
#例:watermark.txt = ${WATERMARK_TXT:凯京科技内部文件,严禁外泄}
|
||||||
|
#如需取消水印,内容设置为空即可,例:watermark.txt = ${WATERMARK_TXT:}
|
||||||
|
watermark.txt = ${WATERMARK_TXT:}
|
||||||
|
#水印x轴间隔
|
||||||
|
watermark.x.space = ${WATERMARK_X_SPACE:10}
|
||||||
|
#水印y轴间隔
|
||||||
|
watermark.y.space = ${WATERMARK_Y_SPACE:10}
|
||||||
|
#水印字体
|
||||||
|
watermark.font = ${WATERMARK_FONT:微软雅黑}
|
||||||
|
#水印字体大小
|
||||||
|
watermark.fontsize = ${WATERMARK_FONTSIZE:18px}
|
||||||
|
#水印字体颜色
|
||||||
|
watermark.color = ${WATERMARK_COLOR:black}
|
||||||
|
#水印透明度,要求设置在大于等于0.005,小于1
|
||||||
|
watermark.alpha = ${WATERMARK_ALPHA:0.2}
|
||||||
|
#水印宽度
|
||||||
|
watermark.width = ${WATERMARK_WIDTH:180}
|
||||||
|
#水印高度
|
||||||
|
watermark.height = ${WATERMARK_HEIGHT:80}
|
||||||
|
#水印倾斜度数,要求设置在大于等于0,小于90
|
||||||
|
watermark.angle = ${WATERMARK_ANGLE:10}
|
||||||
|
|
||||||
@@ -4,15 +4,12 @@ import org.springframework.boot.SpringApplication;
|
|||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.context.annotation.ComponentScan;
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
@EnableScheduling
|
@EnableScheduling
|
||||||
@ComponentScan(value = "cn.keking.*")
|
@ComponentScan(value = "cn.keking.*")
|
||||||
public class FilePreviewApplication {
|
public class FilePreviewApplication {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
Properties properties = System.getProperties();
|
|
||||||
System.out.println(properties.get("user.dir"));
|
|
||||||
SpringApplication.run(FilePreviewApplication.class, args);
|
SpringApplication.run(FilePreviewApplication.class, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,65 +5,201 @@ import org.springframework.beans.factory.annotation.Value;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @auther: chenjh
|
* @author: chenjh
|
||||||
* @time: 2019/4/10 17:22
|
* @since: 2019/4/10 17:22
|
||||||
* @description
|
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class ConfigConstants {
|
public class ConfigConstants {
|
||||||
|
|
||||||
private static String[] simText = {};
|
private static Boolean CACHE_ENABLED;
|
||||||
private static String[] media = {};
|
private static String[] SIM_TEXT = {};
|
||||||
private static String convertedFileCharset;
|
private static String[] MEDIA = {};
|
||||||
private static String officePreviewType;
|
private static String OFFICE_PREVIEW_TYPE;
|
||||||
private static String fileDir = OfficeUtils.getHomePath() + File.separator + "file" + File.separator;
|
private static String FTP_USERNAME;
|
||||||
|
private static String FTP_PASSWORD;
|
||||||
|
private static String FTP_CONTROL_ENCODING;
|
||||||
|
private static String BASE_URL;
|
||||||
|
private static String FILE_DIR = OfficeUtils.getHomePath() + File.separator + "file" + File.separator;
|
||||||
|
private static CopyOnWriteArraySet<String> TRUST_HOST_SET;
|
||||||
|
private static String PDF_DOWNLOAD_DISABLE;
|
||||||
|
|
||||||
public static String[] getSimText() {
|
public static final String DEFAULT_CACHE_ENABLED = "true";
|
||||||
return simText;
|
public static final String DEFAULT_TXT_TYPE = "txt,html,htm,asp,jsp,xml,json,properties,md,gitignore,log,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_OFFICE_PREVIEW_TYPE = "image";
|
||||||
|
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";
|
||||||
|
public static final String DEFAULT_FILE_DIR_VALUE = "default";
|
||||||
|
public static final String DEFAULT_TRUST_HOST = "default";
|
||||||
|
public static final String DEFAULT_PDF_DOWNLOAD_DISABLE = "true";
|
||||||
|
|
||||||
|
public static Boolean isCacheEnabled() {
|
||||||
|
return CACHE_ENABLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setSimText(String[] simText) {
|
@Value("${cache.enabled:true}")
|
||||||
ConfigConstants.simText = simText;
|
public void setCacheEnabled(String cacheEnabled) {
|
||||||
|
setCacheEnabledValueValue(Boolean.parseBoolean(cacheEnabled));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setCacheEnabledValueValue(Boolean cacheEnabled) {
|
||||||
|
CACHE_ENABLED = cacheEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String[] getSimText() {
|
||||||
|
return SIM_TEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Value("${simText:txt,html,htm,asp,jsp,xml,json,properties,md,gitignore,log,java,py,c,cpp,sql,sh,bat,m,bas,prg,cmd}")
|
||||||
|
public void setSimText(String simText) {
|
||||||
|
String[] simTextArr = simText.split(",");
|
||||||
|
setSimTextValue(simTextArr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setSimTextValue(String[] simText) {
|
||||||
|
SIM_TEXT = simText;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String[] getMedia() {
|
public static String[] getMedia() {
|
||||||
return media;
|
return MEDIA;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setMedia(String[] media) {
|
@Value("${media:mp3,wav,mp4,flv}")
|
||||||
ConfigConstants.media = media;
|
public void setMedia(String media) {
|
||||||
|
String[] mediaArr = media.split(",");
|
||||||
|
setMediaValue(mediaArr);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getConvertedFileCharset() {
|
public static void setMediaValue(String[] Media) {
|
||||||
return convertedFileCharset;
|
MEDIA = Media;
|
||||||
}
|
|
||||||
|
|
||||||
public static void setConvertedFileCharset(String convertedFileCharset) {
|
|
||||||
ConfigConstants.convertedFileCharset = convertedFileCharset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getOfficePreviewType() {
|
public static String getOfficePreviewType() {
|
||||||
return officePreviewType;
|
return OFFICE_PREVIEW_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setOfficePreviewType(String officePreviewType) {
|
@Value("${office.preview.type:image}")
|
||||||
ConfigConstants.officePreviewType = officePreviewType;
|
public void setOfficePreviewType(String officePreviewType) {
|
||||||
|
setOfficePreviewTypeValue(officePreviewType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setOfficePreviewTypeValue(String officePreviewType) {
|
||||||
|
OFFICE_PREVIEW_TYPE = officePreviewType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getFtpUsername() {
|
||||||
|
return FTP_USERNAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Value("${ftp.username:}")
|
||||||
|
public void setFtpUsername(String ftpUsername) {
|
||||||
|
setFtpUsernameValue(ftpUsername);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setFtpUsernameValue(String ftpUsername) {
|
||||||
|
FTP_USERNAME = ftpUsername;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getFtpPassword() {
|
||||||
|
return FTP_PASSWORD;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Value("${ftp.password:}")
|
||||||
|
public void setFtpPassword(String ftpPassword) {
|
||||||
|
setFtpPasswordValue(ftpPassword);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setFtpPasswordValue(String ftpPassword) {
|
||||||
|
FTP_PASSWORD = ftpPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getFtpControlEncoding() {
|
||||||
|
return FTP_CONTROL_ENCODING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Value("${ftp.control.encoding:UTF-8}")
|
||||||
|
public void setFtpControlEncoding(String ftpControlEncoding) {
|
||||||
|
setFtpControlEncodingValue(ftpControlEncoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setFtpControlEncodingValue(String ftpControlEncoding) {
|
||||||
|
FTP_CONTROL_ENCODING = ftpControlEncoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getBaseUrl() {
|
||||||
|
return BASE_URL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Value("${base.url:default}")
|
||||||
|
public void setBaseUrl(String baseUrl) {
|
||||||
|
setBaseUrlValue(baseUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setBaseUrlValue(String baseUrl) {
|
||||||
|
BASE_URL = baseUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getFileDir() {
|
public static String getFileDir() {
|
||||||
return fileDir;
|
return FILE_DIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Value("${file.dir:default}")
|
@Value("${file.dir:default}")
|
||||||
public void setFileDir(String fileDir) {
|
public void setFileDir(String fileDir) {
|
||||||
if (!"default".equals(fileDir)) {
|
setFileDirValue(fileDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setFileDirValue(String 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;
|
||||||
}
|
}
|
||||||
ConfigConstants.fileDir = fileDir;
|
FILE_DIR = fileDir;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Value("${trust.host:default}")
|
||||||
|
public void setTrustHost(String trustHost) {
|
||||||
|
setTrustHostValue(trustHost);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setTrustHostValue(String trustHost) {
|
||||||
|
CopyOnWriteArraySet<String> trustHostSet;
|
||||||
|
if (DEFAULT_TRUST_HOST.equals(trustHost.toLowerCase())) {
|
||||||
|
trustHostSet = new CopyOnWriteArraySet<>();
|
||||||
|
} else {
|
||||||
|
String[] trustHostArray = trustHost.toLowerCase().split(",");
|
||||||
|
trustHostSet = new CopyOnWriteArraySet<>(Arrays.asList(trustHostArray));
|
||||||
|
setTrustHostSet(trustHostSet);
|
||||||
|
}
|
||||||
|
setTrustHostSet(trustHostSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Set<String> getTrustHostSet() {
|
||||||
|
return TRUST_HOST_SET;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setTrustHostSet(CopyOnWriteArraySet<String> trustHostSet) {
|
||||||
|
ConfigConstants.TRUST_HOST_SET = trustHostSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getPdfDownloadDisable() {
|
||||||
|
return PDF_DOWNLOAD_DISABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Value("${pdf.download.disable:true}")
|
||||||
|
public void setPdfDownloadDisable(String pdfDownloadDisable) {
|
||||||
|
setPdfDownloadDisableValue(pdfDownloadDisable);
|
||||||
|
}
|
||||||
|
public static void setPdfDownloadDisableValue(String pdfDownloadDisable) {
|
||||||
|
PDF_DOWNLOAD_DISABLE = pdfDownloadDisable;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package cn.keking.config;
|
package cn.keking.config;
|
||||||
|
|
||||||
import cn.keking.service.impl.OfficeFilePreviewImpl;
|
|
||||||
import org.artofsolving.jodconverter.office.OfficeUtils;
|
import org.artofsolving.jodconverter.office.OfficeUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -22,47 +21,89 @@ 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_MEDIA_TYPE = "mp3,wav,mp4,flv";
|
|
||||||
|
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
void refresh() {
|
void refresh() {
|
||||||
Thread configRefreshThread = new Thread(new ConfigRefreshThread());
|
Thread configRefreshThread = new Thread(new ConfigRefreshThread());
|
||||||
configRefreshThread.start();
|
configRefreshThread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
class ConfigRefreshThread implements Runnable {
|
static class ConfigRefreshThread implements Runnable {
|
||||||
@Override
|
@Override
|
||||||
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 baseUrl;
|
||||||
|
String trustHost;
|
||||||
|
String pdfDownloadDisable;
|
||||||
while (true) {
|
while (true) {
|
||||||
BufferedReader bufferedReader = new BufferedReader(new FileReader(configFilePath));
|
FileReader fileReader = new FileReader(configFilePath);
|
||||||
|
BufferedReader bufferedReader = new BufferedReader(fileReader);
|
||||||
properties.load(bufferedReader);
|
properties.load(bufferedReader);
|
||||||
text = properties.getProperty("simText", DEFAULT_TXT_TYPE);
|
OfficeUtils.restorePropertiesFromEnvFormat(properties);
|
||||||
media = properties.getProperty("media", DEFAULT_MEDIA_TYPE);
|
cacheEnabled = Boolean.parseBoolean(properties.getProperty("cache.enabled", ConfigConstants.DEFAULT_CACHE_ENABLED));
|
||||||
convertedFileCharset = properties.getProperty("converted.file.charset", convertedFileCharset);
|
text = properties.getProperty("simText", ConfigConstants.DEFAULT_TXT_TYPE);
|
||||||
officePreviewType = properties.getProperty("office.preview.type", OfficeFilePreviewImpl.OFFICE_PREVIEW_TYPE_IMAGE);
|
media = properties.getProperty("media", ConfigConstants.DEFAULT_MEDIA_TYPE);
|
||||||
|
officePreviewType = properties.getProperty("office.preview.type", ConfigConstants.DEFAULT_OFFICE_PREVIEW_TYPE);
|
||||||
|
ftpUsername = properties.getProperty("ftp.username", ConfigConstants.DEFAULT_FTP_USERNAME);
|
||||||
|
ftpPassword = properties.getProperty("ftp.password", ConfigConstants.DEFAULT_FTP_PASSWORD);
|
||||||
|
ftpControlEncoding = properties.getProperty("ftp.control.encoding", ConfigConstants.DEFAULT_FTP_CONTROL_ENCODING);
|
||||||
textArray = text.split(",");
|
textArray = text.split(",");
|
||||||
mediaArray = media.split(",");
|
mediaArray = media.split(",");
|
||||||
ConfigConstants.setSimText(textArray);
|
baseUrl = properties.getProperty("base.url", ConfigConstants.DEFAULT_BASE_URL);
|
||||||
ConfigConstants.setMedia(mediaArray);
|
trustHost = properties.getProperty("trust.host", ConfigConstants.DEFAULT_TRUST_HOST);
|
||||||
ConfigConstants.setConvertedFileCharset(convertedFileCharset);
|
pdfDownloadDisable = properties.getProperty("pdf.download.disable", ConfigConstants.DEFAULT_PDF_DOWNLOAD_DISABLE);
|
||||||
ConfigConstants.setOfficePreviewType(officePreviewType);
|
ConfigConstants.setCacheEnabledValueValue(cacheEnabled);
|
||||||
|
ConfigConstants.setSimTextValue(textArray);
|
||||||
|
ConfigConstants.setMediaValue(mediaArray);
|
||||||
|
ConfigConstants.setOfficePreviewTypeValue(officePreviewType);
|
||||||
|
ConfigConstants.setFtpUsernameValue(ftpUsername);
|
||||||
|
ConfigConstants.setFtpPasswordValue(ftpPassword);
|
||||||
|
ConfigConstants.setFtpControlEncodingValue(ftpControlEncoding);
|
||||||
|
ConfigConstants.setBaseUrlValue(baseUrl);
|
||||||
|
ConfigConstants.setTrustHostValue(trustHost);
|
||||||
|
ConfigConstants.setPdfDownloadDisableValue(pdfDownloadDisable);
|
||||||
|
setWatermarkConfig(properties);
|
||||||
|
bufferedReader.close();
|
||||||
|
fileReader.close();
|
||||||
Thread.sleep(1000L);
|
Thread.sleep(1000L);
|
||||||
}
|
}
|
||||||
} catch (IOException | InterruptedException e) {
|
} catch (IOException | InterruptedException e) {
|
||||||
LOGGER.error("读取配置文件异常:{}", e);
|
LOGGER.error("读取配置文件异常", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setWatermarkConfig(Properties properties) {
|
||||||
|
String watermarkTxt = properties.getProperty("watermark.txt", WatermarkConfigConstants.DEFAULT_WATERMARK_TXT);
|
||||||
|
String watermarkXSpace = properties.getProperty("watermark.x.space", WatermarkConfigConstants.DEFAULT_WATERMARK_X_SPACE);
|
||||||
|
String watermarkYSpace = properties.getProperty("watermark.y.space", WatermarkConfigConstants.DEFAULT_WATERMARK_Y_SPACE);
|
||||||
|
String watermarkFont = properties.getProperty("watermark.font", WatermarkConfigConstants.DEFAULT_WATERMARK_FONT);
|
||||||
|
String watermarkFontsize = properties.getProperty("watermark.fontsize", WatermarkConfigConstants.DEFAULT_WATERMARK_FONTSIZE);
|
||||||
|
String watermarkColor = properties.getProperty("watermark.color", WatermarkConfigConstants.DEFAULT_WATERMARK_COLOR);
|
||||||
|
String watermarkAlpha = properties.getProperty("watermark.alpha", WatermarkConfigConstants.DEFAULT_WATERMARK_ALPHA);
|
||||||
|
String watermarkWidth = properties.getProperty("watermark.width", WatermarkConfigConstants.DEFAULT_WATERMARK_WIDTH);
|
||||||
|
String watermarkHeight = properties.getProperty("watermark.height", WatermarkConfigConstants.DEFAULT_WATERMARK_HEIGHT);
|
||||||
|
String watermarkAngle = properties.getProperty("watermark.angle", WatermarkConfigConstants.DEFAULT_WATERMARK_ANGLE);
|
||||||
|
WatermarkConfigConstants.setWatermarkTxtValue(watermarkTxt);
|
||||||
|
WatermarkConfigConstants.setWatermarkXSpaceValue(watermarkXSpace);
|
||||||
|
WatermarkConfigConstants.setWatermarkYSpaceValue(watermarkYSpace);
|
||||||
|
WatermarkConfigConstants.setWatermarkFontValue(watermarkFont);
|
||||||
|
WatermarkConfigConstants.setWatermarkFontsizeValue(watermarkFontsize);
|
||||||
|
WatermarkConfigConstants.setWatermarkColorValue(watermarkColor);
|
||||||
|
WatermarkConfigConstants.setWatermarkAlphaValue(watermarkAlpha);
|
||||||
|
WatermarkConfigConstants.setWatermarkWidthValue(watermarkWidth);
|
||||||
|
WatermarkConfigConstants.setWatermarkHeightValue(watermarkHeight);
|
||||||
|
WatermarkConfigConstants.setWatermarkAngleValue(watermarkAngle);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package cn.keking.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author chenjh
|
||||||
|
* @since 2020/5/18 13:41
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class RFCConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Boolean setRequestTargetAllow() {
|
||||||
|
// RFC 7230,RFC 3986规范不允许url相关特殊字符,手动指定Tomcat url允许特殊符号, 如{}做入参,其他符号按需添加。见tomcat的HttpParser源码。
|
||||||
|
System.setProperty("tomcat.util.http.parser.HttpParser.requestTargetAllow", "|{}");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,164 @@
|
|||||||
|
package cn.keking.config;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author chenjh
|
||||||
|
* @since 2020/5/13 17:44
|
||||||
|
*/
|
||||||
|
public class WatermarkConfigConstants {
|
||||||
|
|
||||||
|
private static String WATERMARK_TXT;
|
||||||
|
private static String WATERMARK_X_SPACE;
|
||||||
|
private static String WATERMARK_Y_SPACE;
|
||||||
|
private static String WATERMARK_FONT;
|
||||||
|
private static String WATERMARK_FONTSIZE;
|
||||||
|
private static String WATERMARK_COLOR;
|
||||||
|
private static String WATERMARK_ALPHA;
|
||||||
|
private static String WATERMARK_WIDTH;
|
||||||
|
private static String WATERMARK_HEIGHT;
|
||||||
|
private static String WATERMARK_ANGLE;
|
||||||
|
|
||||||
|
public static String DEFAULT_WATERMARK_TXT = "";
|
||||||
|
public static String DEFAULT_WATERMARK_X_SPACE = "10";
|
||||||
|
public static String DEFAULT_WATERMARK_Y_SPACE = "10";
|
||||||
|
public static String DEFAULT_WATERMARK_FONT = "微软雅黑";
|
||||||
|
public static String DEFAULT_WATERMARK_FONTSIZE = "18px";
|
||||||
|
public static String DEFAULT_WATERMARK_COLOR = "black";
|
||||||
|
public static String DEFAULT_WATERMARK_ALPHA = "0.2";
|
||||||
|
public static String DEFAULT_WATERMARK_WIDTH = "240";
|
||||||
|
public static String DEFAULT_WATERMARK_HEIGHT = "80";
|
||||||
|
public static String DEFAULT_WATERMARK_ANGLE = "10";
|
||||||
|
|
||||||
|
public static String getWatermarkTxt() {
|
||||||
|
return WATERMARK_TXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setWatermarkTxtValue(String watermarkTxt) {
|
||||||
|
WATERMARK_TXT = watermarkTxt;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Value("${watermark.txt:}")
|
||||||
|
public void setWatermarkTxt(String watermarkTxt) {
|
||||||
|
setWatermarkTxtValue(watermarkTxt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getWatermarkXSpace() {
|
||||||
|
return WATERMARK_X_SPACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setWatermarkXSpaceValue(String watermarkXSpace) {
|
||||||
|
WATERMARK_X_SPACE = watermarkXSpace;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Value("${watermark.x.space:10}")
|
||||||
|
public void setWatermarkXSpace(String watermarkXSpace) {
|
||||||
|
setWatermarkXSpaceValue(watermarkXSpace);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getWatermarkYSpace() {
|
||||||
|
return WATERMARK_Y_SPACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setWatermarkYSpaceValue(String watermarkYSpace) {
|
||||||
|
WATERMARK_Y_SPACE = watermarkYSpace;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Value("${watermark.y.space:10}")
|
||||||
|
public void setWatermarkYSpace(String watermarkYSpace) {
|
||||||
|
setWatermarkYSpaceValue(watermarkYSpace);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getWatermarkFont() {
|
||||||
|
return WATERMARK_FONT;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setWatermarkFontValue(String watermarkFont) {
|
||||||
|
WATERMARK_FONT = watermarkFont;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Value("${watermark.font:微软雅黑}")
|
||||||
|
public void setWatermarkFont(String watermarkFont) {
|
||||||
|
setWatermarkFontValue(watermarkFont);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getWatermarkFontsize() {
|
||||||
|
return WATERMARK_FONTSIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setWatermarkFontsizeValue(String watermarkFontsize) {
|
||||||
|
WATERMARK_FONTSIZE = watermarkFontsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Value("${watermark.fontsize:18px}")
|
||||||
|
public void setWatermarkFontsize(String watermarkFontsize) {
|
||||||
|
setWatermarkFontsizeValue(watermarkFontsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getWatermarkColor() {
|
||||||
|
return WATERMARK_COLOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setWatermarkColorValue(String watermarkColor) {
|
||||||
|
WATERMARK_COLOR = watermarkColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Value("${watermark.color:black}")
|
||||||
|
public void setWatermarkColor(String watermarkColor) {
|
||||||
|
setWatermarkColorValue(watermarkColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getWatermarkAlpha() {
|
||||||
|
return WATERMARK_ALPHA;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setWatermarkAlphaValue(String watermarkAlpha) {
|
||||||
|
WATERMARK_ALPHA = watermarkAlpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Value("${watermark.alpha:0.2}")
|
||||||
|
public void setWatermarkAlpha(String watermarkAlpha) {
|
||||||
|
setWatermarkAlphaValue(watermarkAlpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getWatermarkWidth() {
|
||||||
|
return WATERMARK_WIDTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setWatermarkWidthValue(String watermarkWidth) {
|
||||||
|
WATERMARK_WIDTH = watermarkWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Value("${watermark.width:240}")
|
||||||
|
public void setWatermarkWidth(String watermarkWidth) {
|
||||||
|
WATERMARK_WIDTH = watermarkWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getWatermarkHeight() {
|
||||||
|
return WATERMARK_HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setWatermarkHeightValue(String watermarkHeight) {
|
||||||
|
WATERMARK_HEIGHT = watermarkHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Value("${watermark.height:80}")
|
||||||
|
public void setWatermarkHeight(String watermarkHeight) {
|
||||||
|
WATERMARK_HEIGHT = watermarkHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getWatermarkAngle() {
|
||||||
|
return WATERMARK_ANGLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setWatermarkAngleValue(String watermarkAngle) {
|
||||||
|
WATERMARK_ANGLE = watermarkAngle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Value("${watermark.angle:10}")
|
||||||
|
public void setWatermarkAngle(String watermarkAngle) {
|
||||||
|
WATERMARK_ANGLE = watermarkAngle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -7,9 +7,8 @@ import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry
|
|||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @auther: chenjh
|
* @author: chenjh
|
||||||
* @time: 2019/4/16 20:04
|
* @since: 2019/4/16 20:04
|
||||||
* @description
|
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
public class WebConfig extends WebMvcConfigurerAdapter {
|
public class WebConfig extends WebMvcConfigurerAdapter {
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package cn.keking.extend;
|
package cn.keking.extend;
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import com.sun.star.beans.PropertyValue;
|
|
||||||
import org.artofsolving.jodconverter.document.DocumentFamily;
|
import org.artofsolving.jodconverter.document.DocumentFamily;
|
||||||
import org.artofsolving.jodconverter.document.DocumentFormat;
|
import org.artofsolving.jodconverter.document.DocumentFormat;
|
||||||
import org.artofsolving.jodconverter.document.SimpleDocumentFormatRegistry;
|
import org.artofsolving.jodconverter.document.SimpleDocumentFormatRegistry;
|
||||||
@@ -42,7 +40,7 @@ public class ControlDocumentFormatRegistry extends SimpleDocumentFormatRegistry
|
|||||||
// available for exporting Spreadsheet and Presentation formats
|
// available for exporting Spreadsheet and Presentation formats
|
||||||
html.setInputFamily(DocumentFamily.TEXT);
|
html.setInputFamily(DocumentFamily.TEXT);
|
||||||
html.setStoreProperties(DocumentFamily.TEXT, Collections.singletonMap("FilterName", "HTML (StarWriter)"));
|
html.setStoreProperties(DocumentFamily.TEXT, Collections.singletonMap("FilterName", "HTML (StarWriter)"));
|
||||||
Map<String,Object> htmlLoadAndStoreProperties = new LinkedHashMap<String,Object>();
|
Map<String,Object> htmlLoadAndStoreProperties = new LinkedHashMap<>();
|
||||||
htmlLoadAndStoreProperties.put("FilterName", "HTML (StarCalc)");
|
htmlLoadAndStoreProperties.put("FilterName", "HTML (StarCalc)");
|
||||||
htmlLoadAndStoreProperties.put("FilterOptions", "utf8");
|
htmlLoadAndStoreProperties.put("FilterOptions", "utf8");
|
||||||
html.setStoreProperties(DocumentFamily.SPREADSHEET, htmlLoadAndStoreProperties);
|
html.setStoreProperties(DocumentFamily.SPREADSHEET, htmlLoadAndStoreProperties);
|
||||||
@@ -79,7 +77,7 @@ public class ControlDocumentFormatRegistry extends SimpleDocumentFormatRegistry
|
|||||||
|
|
||||||
DocumentFormat txt = new DocumentFormat("Plain Text", "txt", "text/plain");
|
DocumentFormat txt = new DocumentFormat("Plain Text", "txt", "text/plain");
|
||||||
txt.setInputFamily(DocumentFamily.TEXT);
|
txt.setInputFamily(DocumentFamily.TEXT);
|
||||||
Map<String,Object> txtLoadAndStoreProperties = new LinkedHashMap<String,Object>();
|
Map<String,Object> txtLoadAndStoreProperties = new LinkedHashMap<>();
|
||||||
txtLoadAndStoreProperties.put("FilterName", "Text (encoded)");
|
txtLoadAndStoreProperties.put("FilterName", "Text (encoded)");
|
||||||
txtLoadAndStoreProperties.put("FilterOptions", "utf8");
|
txtLoadAndStoreProperties.put("FilterOptions", "utf8");
|
||||||
txt.setLoadProperties(txtLoadAndStoreProperties);
|
txt.setLoadProperties(txtLoadAndStoreProperties);
|
||||||
@@ -111,7 +109,7 @@ public class ControlDocumentFormatRegistry extends SimpleDocumentFormatRegistry
|
|||||||
|
|
||||||
DocumentFormat csv = new DocumentFormat("Comma Separated Values", "csv", "text/csv");
|
DocumentFormat csv = new DocumentFormat("Comma Separated Values", "csv", "text/csv");
|
||||||
csv.setInputFamily(DocumentFamily.SPREADSHEET);
|
csv.setInputFamily(DocumentFamily.SPREADSHEET);
|
||||||
Map<String,Object> csvLoadAndStoreProperties = new LinkedHashMap<String,Object>();
|
Map<String,Object> csvLoadAndStoreProperties = new LinkedHashMap<>();
|
||||||
csvLoadAndStoreProperties.put("FilterName", "Text - txt - csv (StarCalc)");
|
csvLoadAndStoreProperties.put("FilterName", "Text - txt - csv (StarCalc)");
|
||||||
csvLoadAndStoreProperties.put("FilterOptions", "44,34,0"); // Field Separator: ','; Text Delimiter: '"'
|
csvLoadAndStoreProperties.put("FilterOptions", "44,34,0"); // Field Separator: ','; Text Delimiter: '"'
|
||||||
csv.setLoadProperties(csvLoadAndStoreProperties);
|
csv.setLoadProperties(csvLoadAndStoreProperties);
|
||||||
@@ -120,7 +118,7 @@ public class ControlDocumentFormatRegistry extends SimpleDocumentFormatRegistry
|
|||||||
|
|
||||||
DocumentFormat tsv = new DocumentFormat("Tab Separated Values", "tsv", "text/tab-separated-values");
|
DocumentFormat tsv = new DocumentFormat("Tab Separated Values", "tsv", "text/tab-separated-values");
|
||||||
tsv.setInputFamily(DocumentFamily.SPREADSHEET);
|
tsv.setInputFamily(DocumentFamily.SPREADSHEET);
|
||||||
Map<String,Object> tsvLoadAndStoreProperties = new LinkedHashMap<String,Object>();
|
Map<String,Object> tsvLoadAndStoreProperties = new LinkedHashMap<>();
|
||||||
tsvLoadAndStoreProperties.put("FilterName", "Text - txt - csv (StarCalc)");
|
tsvLoadAndStoreProperties.put("FilterName", "Text - txt - csv (StarCalc)");
|
||||||
tsvLoadAndStoreProperties.put("FilterOptions", "9,34,0"); // Field Separator: '\t'; Text Delimiter: '"'
|
tsvLoadAndStoreProperties.put("FilterOptions", "9,34,0"); // Field Separator: '\t'; Text Delimiter: '"'
|
||||||
tsv.setLoadProperties(tsvLoadAndStoreProperties);
|
tsv.setLoadProperties(tsvLoadAndStoreProperties);
|
||||||
@@ -156,56 +154,4 @@ public class ControlDocumentFormatRegistry extends SimpleDocumentFormatRegistry
|
|||||||
addFormat(svg);
|
addFormat(svg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建默认的导出属性
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private PropertyValue[] getCommonPropertyValue() {
|
|
||||||
PropertyValue[] aFilterData = new PropertyValue[11];
|
|
||||||
// 不显示文档标题
|
|
||||||
aFilterData[0] = new PropertyValue();
|
|
||||||
aFilterData[0].Name = "DisplayPDFDocumentTitle";
|
|
||||||
aFilterData[0].Value= true;
|
|
||||||
// 导出文件编码方式
|
|
||||||
aFilterData[1] = new PropertyValue();
|
|
||||||
aFilterData[1].Name = "Encoding";
|
|
||||||
aFilterData[1].Value= "UTF-8";
|
|
||||||
// 隐藏工具条
|
|
||||||
aFilterData[2] = new PropertyValue();
|
|
||||||
aFilterData[2].Name = "HideViewerToolbar";
|
|
||||||
aFilterData[2].Value= false;
|
|
||||||
// 隐藏窗口控制条
|
|
||||||
aFilterData[3] = new PropertyValue();
|
|
||||||
aFilterData[3].Name = "HideViewerWindowControls";
|
|
||||||
aFilterData[3].Value= true;
|
|
||||||
// 全屏展示
|
|
||||||
aFilterData[4] = new PropertyValue();
|
|
||||||
aFilterData[4].Name = "OpenInFullScreenMode";
|
|
||||||
aFilterData[4].Value= false;
|
|
||||||
// 第一页左边展示
|
|
||||||
aFilterData[5] = new PropertyValue();
|
|
||||||
aFilterData[5].Name = "MathToMathType";
|
|
||||||
aFilterData[5].Value= true;
|
|
||||||
// 文档标题内容
|
|
||||||
aFilterData[6] = new PropertyValue();
|
|
||||||
aFilterData[6].Name = "Watermark";
|
|
||||||
aFilterData[6].Value= "KEKING.CN";
|
|
||||||
// 导出文件编码方式
|
|
||||||
aFilterData[7] = new PropertyValue();
|
|
||||||
aFilterData[7].Name = "CharacterSet";
|
|
||||||
aFilterData[7].Value= "UTF-8";
|
|
||||||
// 导出文件编码方式
|
|
||||||
aFilterData[8] = new PropertyValue();
|
|
||||||
aFilterData[8].Name = "Encoding";
|
|
||||||
aFilterData[8].Value= "UTF-8";
|
|
||||||
// 导出文件编码方式
|
|
||||||
aFilterData[9] = new PropertyValue();
|
|
||||||
aFilterData[9].Name = "CharSet";
|
|
||||||
aFilterData[9].Value= "UTF-8";
|
|
||||||
// 导出文件编码方式
|
|
||||||
aFilterData[10] = new PropertyValue();
|
|
||||||
aFilterData[10].Name = "charset";
|
|
||||||
aFilterData[10].Value= "UTF-8";
|
|
||||||
return aFilterData;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
package cn.keking.filters;
|
|
||||||
|
|
||||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author yudian-it
|
|
||||||
* @date 2017/11/30
|
|
||||||
*/
|
|
||||||
@Configuration
|
|
||||||
public class FilterConfiguration {
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public FilterRegistrationBean getChinesePathFilter(){
|
|
||||||
ChinesePathFilter filter = new ChinesePathFilter();
|
|
||||||
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
|
|
||||||
registrationBean.setFilter(filter);
|
|
||||||
return registrationBean;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
388
jodconverter-web/src/main/java/cn/keking/hutool/HexUtil.java
Normal file
388
jodconverter-web/src/main/java/cn/keking/hutool/HexUtil.java
Normal file
@@ -0,0 +1,388 @@
|
|||||||
|
package cn.keking.hutool;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 十六进制(简写为hex或下标16)在数学中是一种逢16进1的进位制,一般用数字0到9和字母A到F表示(其中:A~F即10~15)。<br>
|
||||||
|
* 例如十进制数57,在二进制写作111001,在16进制写作39。<br>
|
||||||
|
* 像java,c这样的语言为了区分十六进制和十进制数值,会在十六进制数的前面加上 0x,比如0x20是十进制的32,而不是十进制的20<br>
|
||||||
|
* <p>
|
||||||
|
* 参考:https://my.oschina.net/xinxingegeya/blog/287476
|
||||||
|
*
|
||||||
|
* @author Looly
|
||||||
|
*/
|
||||||
|
public class HexUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于建立十六进制字符的输出的小写字符数组
|
||||||
|
*/
|
||||||
|
private static final char[] DIGITS_LOWER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||||
|
/**
|
||||||
|
* 用于建立十六进制字符的输出的大写字符数组
|
||||||
|
*/
|
||||||
|
private static final char[] DIGITS_UPPER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断给定字符串是否为16进制数<br>
|
||||||
|
* 如果是,需要使用对应数字类型对象的<code>decode</code>方法解码<br>
|
||||||
|
* 例如:{@code Integer.decode}方法解码int类型的16进制数字
|
||||||
|
*
|
||||||
|
* @param value 值
|
||||||
|
* @return 是否为16进制
|
||||||
|
*/
|
||||||
|
public static boolean isHexNumber(String value) {
|
||||||
|
final int index = (value.startsWith("-") ? 1 : 0);
|
||||||
|
if (value.startsWith("0x", index) || value.startsWith("0X", index) || value.startsWith("#", index)) {
|
||||||
|
try {
|
||||||
|
Long.decode(value);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------------- encode
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将字节数组转换为十六进制字符数组
|
||||||
|
*
|
||||||
|
* @param data byte[]
|
||||||
|
* @return 十六进制char[]
|
||||||
|
*/
|
||||||
|
public static char[] encodeHex(byte[] data) {
|
||||||
|
return encodeHex(data, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将字节数组转换为十六进制字符数组
|
||||||
|
*
|
||||||
|
* @param str 字符串
|
||||||
|
* @param charset 编码
|
||||||
|
* @return 十六进制char[]
|
||||||
|
*/
|
||||||
|
public static char[] encodeHex(String str, Charset charset) {
|
||||||
|
return encodeHex(StrUtil.bytes(str, charset), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将字节数组转换为十六进制字符数组
|
||||||
|
*
|
||||||
|
* @param data byte[]
|
||||||
|
* @param toLowerCase <code>true</code> 传换成小写格式 , <code>false</code> 传换成大写格式
|
||||||
|
* @return 十六进制char[]
|
||||||
|
*/
|
||||||
|
public static char[] encodeHex(byte[] data, boolean toLowerCase) {
|
||||||
|
return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将字节数组转换为十六进制字符串
|
||||||
|
*
|
||||||
|
* @param data byte[]
|
||||||
|
* @return 十六进制String
|
||||||
|
*/
|
||||||
|
public static String encodeHexStr(byte[] data) {
|
||||||
|
return encodeHexStr(data, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将字节数组转换为十六进制字符串,结果为小写
|
||||||
|
*
|
||||||
|
* @param data 被编码的字符串
|
||||||
|
* @param charset 编码
|
||||||
|
* @return 十六进制String
|
||||||
|
*/
|
||||||
|
public static String encodeHexStr(String data, Charset charset) {
|
||||||
|
return encodeHexStr(StrUtil.bytes(data, charset), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将字节数组转换为十六进制字符串,结果为小写,默认编码是UTF-8
|
||||||
|
*
|
||||||
|
* @param data 被编码的字符串
|
||||||
|
* @return 十六进制String
|
||||||
|
*/
|
||||||
|
public static String encodeHexStr(String data) {
|
||||||
|
return encodeHexStr(data, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将字节数组转换为十六进制字符串
|
||||||
|
*
|
||||||
|
* @param data byte[]
|
||||||
|
* @param toLowerCase <code>true</code> 传换成小写格式 , <code>false</code> 传换成大写格式
|
||||||
|
* @return 十六进制String
|
||||||
|
*/
|
||||||
|
public static String encodeHexStr(byte[] data, boolean toLowerCase) {
|
||||||
|
return encodeHexStr(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------------- decode
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将十六进制字符数组转换为字符串,默认编码UTF-8
|
||||||
|
*
|
||||||
|
* @param hexStr 十六进制String
|
||||||
|
* @return 字符串
|
||||||
|
*/
|
||||||
|
public static String decodeHexStr(String hexStr) {
|
||||||
|
return decodeHexStr(hexStr, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将十六进制字符数组转换为字符串
|
||||||
|
*
|
||||||
|
* @param hexStr 十六进制String
|
||||||
|
* @param charset 编码
|
||||||
|
* @return 字符串
|
||||||
|
*/
|
||||||
|
public static String decodeHexStr(String hexStr, Charset charset) {
|
||||||
|
if (StrUtil.isEmpty(hexStr)) {
|
||||||
|
return hexStr;
|
||||||
|
}
|
||||||
|
return decodeHexStr(hexStr.toCharArray(), charset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将十六进制字符数组转换为字符串
|
||||||
|
*
|
||||||
|
* @param hexData 十六进制char[]
|
||||||
|
* @param charset 编码
|
||||||
|
* @return 字符串
|
||||||
|
*/
|
||||||
|
public static String decodeHexStr(char[] hexData, Charset charset) {
|
||||||
|
return StrUtil.str(decodeHex(hexData), charset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将十六进制字符数组转换为字节数组
|
||||||
|
*
|
||||||
|
* @param hexData 十六进制char[]
|
||||||
|
* @return byte[]
|
||||||
|
* @throws RuntimeException 如果源十六进制字符数组是一个奇怪的长度,将抛出运行时异常
|
||||||
|
*/
|
||||||
|
public static byte[] decodeHex(char[] hexData) {
|
||||||
|
|
||||||
|
int len = hexData.length;
|
||||||
|
|
||||||
|
if ((len & 0x01) != 0) {
|
||||||
|
throw new RuntimeException("Odd number of characters.");
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] out = new byte[len >> 1];
|
||||||
|
|
||||||
|
// two characters form the hex value.
|
||||||
|
for (int i = 0, j = 0; j < len; i++) {
|
||||||
|
int f = toDigit(hexData[j], j) << 4;
|
||||||
|
j++;
|
||||||
|
f = f | toDigit(hexData[j], j);
|
||||||
|
j++;
|
||||||
|
out[i] = (byte) (f & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将十六进制字符串解码为byte[]
|
||||||
|
*
|
||||||
|
* @param hexStr 十六进制String
|
||||||
|
* @return byte[]
|
||||||
|
*/
|
||||||
|
public static byte[] decodeHex(String hexStr) {
|
||||||
|
if (StrUtil.isEmpty(hexStr)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return decodeHex(hexStr.toCharArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------- Color
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将{@link Color}编码为Hex形式
|
||||||
|
*
|
||||||
|
* @param color {@link Color}
|
||||||
|
* @return Hex字符串
|
||||||
|
* @since 3.0.8
|
||||||
|
*/
|
||||||
|
public static String encodeColor(Color color) {
|
||||||
|
return encodeColor(color, "#");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将{@link Color}编码为Hex形式
|
||||||
|
*
|
||||||
|
* @param color {@link Color}
|
||||||
|
* @param prefix 前缀字符串,可以是#、0x等
|
||||||
|
* @return Hex字符串
|
||||||
|
* @since 3.0.8
|
||||||
|
*/
|
||||||
|
public static String encodeColor(Color color, String prefix) {
|
||||||
|
final StringBuilder builder = new StringBuilder(prefix);
|
||||||
|
String colorHex;
|
||||||
|
colorHex = Integer.toHexString(color.getRed());
|
||||||
|
if (1 == colorHex.length()) {
|
||||||
|
builder.append('0');
|
||||||
|
}
|
||||||
|
builder.append(colorHex);
|
||||||
|
colorHex = Integer.toHexString(color.getGreen());
|
||||||
|
if (1 == colorHex.length()) {
|
||||||
|
builder.append('0');
|
||||||
|
}
|
||||||
|
builder.append(colorHex);
|
||||||
|
colorHex = Integer.toHexString(color.getBlue());
|
||||||
|
if (1 == colorHex.length()) {
|
||||||
|
builder.append('0');
|
||||||
|
}
|
||||||
|
builder.append(colorHex);
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将Hex颜色值转为
|
||||||
|
*
|
||||||
|
* @param hexColor 16进制颜色值,可以以#开头,也可以用0x开头
|
||||||
|
* @return {@link Color}
|
||||||
|
* @since 3.0.8
|
||||||
|
*/
|
||||||
|
public static Color decodeColor(String hexColor) {
|
||||||
|
return Color.decode(hexColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将指定int值转换为Unicode字符串形式,常用于特殊字符(例如汉字)转Unicode形式<br>
|
||||||
|
* 转换的字符串如果u后不足4位,则前面用0填充,例如:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* '我' =》\u4f60
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param value int值,也可以是char
|
||||||
|
* @return Unicode表现形式
|
||||||
|
*/
|
||||||
|
public static String toUnicodeHex(int value) {
|
||||||
|
final StringBuilder builder = new StringBuilder(6);
|
||||||
|
|
||||||
|
builder.append("\\u");
|
||||||
|
String hex = toHex(value);
|
||||||
|
int len = hex.length();
|
||||||
|
if (len < 4) {
|
||||||
|
builder.append("0000", 0, 4 - len);// 不足4位补0
|
||||||
|
}
|
||||||
|
builder.append(hex);
|
||||||
|
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将指定char值转换为Unicode字符串形式,常用于特殊字符(例如汉字)转Unicode形式<br>
|
||||||
|
* 转换的字符串如果u后不足4位,则前面用0填充,例如:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* '我' =》\u4f60
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param ch char值
|
||||||
|
* @return Unicode表现形式
|
||||||
|
* @since 4.0.1
|
||||||
|
*/
|
||||||
|
public static String toUnicodeHex(char ch) {
|
||||||
|
return "\\u" +//
|
||||||
|
DIGITS_LOWER[(ch >> 12) & 15] +//
|
||||||
|
DIGITS_LOWER[(ch >> 8) & 15] +//
|
||||||
|
DIGITS_LOWER[(ch >> 4) & 15] +//
|
||||||
|
DIGITS_LOWER[(ch) & 15];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转为16进制字符串
|
||||||
|
*
|
||||||
|
* @param value int值
|
||||||
|
* @return 16进制字符串
|
||||||
|
* @since 4.4.1
|
||||||
|
*/
|
||||||
|
public static String toHex(int value) {
|
||||||
|
return Integer.toHexString(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转为16进制字符串
|
||||||
|
*
|
||||||
|
* @param value int值
|
||||||
|
* @return 16进制字符串
|
||||||
|
* @since 4.4.1
|
||||||
|
*/
|
||||||
|
public static String toHex(long value) {
|
||||||
|
return Long.toHexString(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将byte值转为16进制并添加到{@link StringBuilder}中
|
||||||
|
*
|
||||||
|
* @param builder {@link StringBuilder}
|
||||||
|
* @param b byte
|
||||||
|
* @param toLowerCase 是否使用小写
|
||||||
|
* @since 4.4.1
|
||||||
|
*/
|
||||||
|
public static void appendHex(StringBuilder builder, byte b, boolean toLowerCase) {
|
||||||
|
final char[] toDigits = toLowerCase ? DIGITS_LOWER : DIGITS_UPPER;
|
||||||
|
|
||||||
|
int high = (b & 0xf0) >>> 4;//高位
|
||||||
|
int low = b & 0x0f;//低位
|
||||||
|
builder.append(toDigits[high]);
|
||||||
|
builder.append(toDigits[low]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------- Private method start
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将字节数组转换为十六进制字符串
|
||||||
|
*
|
||||||
|
* @param data byte[]
|
||||||
|
* @param toDigits 用于控制输出的char[]
|
||||||
|
* @return 十六进制String
|
||||||
|
*/
|
||||||
|
private static String encodeHexStr(byte[] data, char[] toDigits) {
|
||||||
|
return new String(encodeHex(data, toDigits));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将字节数组转换为十六进制字符数组
|
||||||
|
*
|
||||||
|
* @param data byte[]
|
||||||
|
* @param toDigits 用于控制输出的char[]
|
||||||
|
* @return 十六进制char[]
|
||||||
|
*/
|
||||||
|
private static char[] encodeHex(byte[] data, char[] toDigits) {
|
||||||
|
final int len = data.length;
|
||||||
|
final char[] out = new char[len << 1];//len*2
|
||||||
|
// two characters from the hex value.
|
||||||
|
for (int i = 0, j = 0; i < len; i++) {
|
||||||
|
out[j++] = toDigits[(0xF0 & data[i]) >>> 4];// 高位
|
||||||
|
out[j++] = toDigits[0x0F & data[i]];// 低位
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将十六进制字符转换成一个整数
|
||||||
|
*
|
||||||
|
* @param ch 十六进制char
|
||||||
|
* @param index 十六进制字符在字符数组中的位置
|
||||||
|
* @return 一个整数
|
||||||
|
* @throws RuntimeException 当ch不是一个合法的十六进制字符时,抛出运行时异常
|
||||||
|
*/
|
||||||
|
private static int toDigit(char ch, int index) {
|
||||||
|
int digit = Character.digit(ch, 16);
|
||||||
|
if (digit == -1) {
|
||||||
|
throw new RuntimeException("Illegal hexadecimal character " + ch + " at index " + index);
|
||||||
|
}
|
||||||
|
return digit;
|
||||||
|
}
|
||||||
|
// ---------------------------------------------------------------------------------------- Private method end
|
||||||
|
}
|
||||||
283
jodconverter-web/src/main/java/cn/keking/hutool/StrUtil.java
Normal file
283
jodconverter-web/src/main/java/cn/keking/hutool/StrUtil.java
Normal file
@@ -0,0 +1,283 @@
|
|||||||
|
package cn.keking.hutool;
|
||||||
|
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符串工具类
|
||||||
|
*
|
||||||
|
* @author xiaoleilu
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class StrUtil {
|
||||||
|
|
||||||
|
public static final String EMPTY = "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否空白符<br>
|
||||||
|
* 空白符包括空格、制表符、全角空格和不间断空格<br>
|
||||||
|
*
|
||||||
|
* @see Character#isWhitespace(int)
|
||||||
|
* @see Character#isSpaceChar(int)
|
||||||
|
* @param c 字符
|
||||||
|
* @return 是否空白符
|
||||||
|
* @since 4.0.10
|
||||||
|
*/
|
||||||
|
public static boolean isBlankChar(int c) {
|
||||||
|
return Character.isWhitespace(c) || Character.isSpaceChar(c) || c == '\ufeff' || c == '\u202a';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否空白符<br>
|
||||||
|
* 空白符包括空格、制表符、全角空格和不间断空格<br>
|
||||||
|
*
|
||||||
|
* @param c 字符
|
||||||
|
* @return 是否空白符
|
||||||
|
* @see Character#isWhitespace(int)
|
||||||
|
* @see Character#isSpaceChar(int)
|
||||||
|
* @since 4.0.10
|
||||||
|
*/
|
||||||
|
public static boolean isBlankChar(char c) {
|
||||||
|
return isBlankChar((int) c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符串是否为空白 空白的定义如下: <br>
|
||||||
|
* 1、为null <br>
|
||||||
|
* 2、为不可见字符(如空格)<br>
|
||||||
|
* 3、""<br>
|
||||||
|
*
|
||||||
|
* @param str 被检测的字符串
|
||||||
|
* @return 是否为空
|
||||||
|
*/
|
||||||
|
public static boolean isBlank(CharSequence str) {
|
||||||
|
int length;
|
||||||
|
|
||||||
|
if ((str == null) || ((length = str.length()) == 0)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
// 只要有一个非空字符即为非空字符串
|
||||||
|
if (false == isBlankChar(str.charAt(i))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符串是否为空,空的定义如下:<br>
|
||||||
|
* 1、为null <br>
|
||||||
|
* 2、为""<br>
|
||||||
|
*
|
||||||
|
* @param str 被检测的字符串
|
||||||
|
* @return 是否为空
|
||||||
|
*/
|
||||||
|
public static boolean isEmpty(CharSequence str) {
|
||||||
|
return str == null || str.length() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编码字符串
|
||||||
|
*
|
||||||
|
* @param str 字符串
|
||||||
|
* @param charset 字符集,如果此字段为空,则解码的结果取决于平台
|
||||||
|
* @return 编码后的字节码
|
||||||
|
*/
|
||||||
|
public static byte[] bytes(CharSequence str, Charset charset) {
|
||||||
|
if (str == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null == charset) {
|
||||||
|
return str.toString().getBytes();
|
||||||
|
}
|
||||||
|
return str.toString().getBytes(charset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link CharSequence} 转为字符串,null安全
|
||||||
|
*
|
||||||
|
* @param cs {@link CharSequence}
|
||||||
|
* @return 字符串
|
||||||
|
*/
|
||||||
|
public static String str(CharSequence cs) {
|
||||||
|
return null == cs ? null : cs.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解码字节码
|
||||||
|
*
|
||||||
|
* @param data 字符串
|
||||||
|
* @param charset 字符集,如果此字段为空,则解码的结果取决于平台
|
||||||
|
* @return 解码后的字符串
|
||||||
|
*/
|
||||||
|
public static String str(byte[] data, Charset charset) {
|
||||||
|
if (data == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null == charset) {
|
||||||
|
return new String(data);
|
||||||
|
}
|
||||||
|
return new String(data, charset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 改进JDK subString<br>
|
||||||
|
* index从0开始计算,最后一个字符为-1<br>
|
||||||
|
* 如果from和to位置一样,返回 "" <br>
|
||||||
|
* 如果from或to为负数,则按照length从后向前数位置,如果绝对值大于字符串长度,则from归到0,to归到length<br>
|
||||||
|
* 如果经过修正的index中from大于to,则互换from和to example: <br>
|
||||||
|
* abcdefgh 2 3 =》 c <br>
|
||||||
|
* abcdefgh 2 -3 =》 cde <br>
|
||||||
|
*
|
||||||
|
* @param str String
|
||||||
|
* @param fromIndex 开始的index(包括)
|
||||||
|
* @param toIndex 结束的index(不包括)
|
||||||
|
* @return 字串
|
||||||
|
*/
|
||||||
|
public static String sub(CharSequence str, int fromIndex, int toIndex) {
|
||||||
|
if (isEmpty(str)) {
|
||||||
|
return str(str);
|
||||||
|
}
|
||||||
|
int len = str.length();
|
||||||
|
|
||||||
|
if (fromIndex < 0) {
|
||||||
|
fromIndex = len + fromIndex;
|
||||||
|
if (fromIndex < 0) {
|
||||||
|
fromIndex = 0;
|
||||||
|
}
|
||||||
|
} else if (fromIndex > len) {
|
||||||
|
fromIndex = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toIndex < 0) {
|
||||||
|
toIndex = len + toIndex;
|
||||||
|
if (toIndex < 0) {
|
||||||
|
toIndex = len;
|
||||||
|
}
|
||||||
|
} else if (toIndex > len) {
|
||||||
|
toIndex = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toIndex < fromIndex) {
|
||||||
|
int tmp = fromIndex;
|
||||||
|
fromIndex = toIndex;
|
||||||
|
toIndex = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fromIndex == toIndex) {
|
||||||
|
return EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return str.toString().substring(fromIndex, toIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 切割指定位置之前部分的字符串
|
||||||
|
*
|
||||||
|
* @param string 字符串
|
||||||
|
* @param toIndex 切割到的位置(不包括)
|
||||||
|
* @return 切割后的剩余的前半部分字符串
|
||||||
|
*/
|
||||||
|
public static String subPre(CharSequence string, int toIndex) {
|
||||||
|
return sub(string, 0, toIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 切割指定位置之后部分的字符串
|
||||||
|
*
|
||||||
|
* @param string 字符串
|
||||||
|
* @param fromIndex 切割开始的位置(包括)
|
||||||
|
* @return 切割后后剩余的后半部分字符串
|
||||||
|
*/
|
||||||
|
public static String subSuf(CharSequence string, int fromIndex) {
|
||||||
|
if (isEmpty(string)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return sub(string, fromIndex, string.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指定范围内查找指定字符
|
||||||
|
*
|
||||||
|
* @param str 字符串
|
||||||
|
* @param searchChar 被查找的字符
|
||||||
|
* @param start 起始位置,如果小于0,从0开始查找
|
||||||
|
* @param end 终止位置,如果超过str.length()则默认查找到字符串末尾
|
||||||
|
* @return 位置
|
||||||
|
*/
|
||||||
|
public static int indexOf(final CharSequence str, char searchChar, int start, int end) {
|
||||||
|
final int len = str.length();
|
||||||
|
if (start < 0 || start > len) {
|
||||||
|
start = 0;
|
||||||
|
}
|
||||||
|
if (end > len || end < 0) {
|
||||||
|
end = len;
|
||||||
|
}
|
||||||
|
for (int i = start; i < end; i++) {
|
||||||
|
if (str.charAt(i) == searchChar) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指定范围内查找指定字符
|
||||||
|
*
|
||||||
|
* @param str 字符串
|
||||||
|
* @param searchChar 被查找的字符
|
||||||
|
* @param start 起始位置,如果小于0,从0开始查找
|
||||||
|
* @return 位置
|
||||||
|
*/
|
||||||
|
public static int indexOf(final CharSequence str, char searchChar, int start) {
|
||||||
|
if (str instanceof String) {
|
||||||
|
return ((String) str).indexOf(searchChar, start);
|
||||||
|
} else {
|
||||||
|
return indexOf(str, searchChar, start, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指定范围内查找指定字符
|
||||||
|
*
|
||||||
|
* @param str 字符串
|
||||||
|
* @param searchChar 被查找的字符
|
||||||
|
* @return 位置
|
||||||
|
*/
|
||||||
|
public static int indexOf(final CharSequence str, char searchChar) {
|
||||||
|
return indexOf(str, searchChar, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 如果字符串是<code>null</code>,则返回指定默认字符串,否则返回字符串本身。
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* nullToDefault(null, "default") = "default"
|
||||||
|
* nullToDefault("", "default") = ""
|
||||||
|
* nullToDefault(" ", "default") = " "
|
||||||
|
* nullToDefault("bat", "default") = "bat"
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param str 要转换的字符串
|
||||||
|
* @param defaultStr 默认字符串
|
||||||
|
*
|
||||||
|
* @return 字符串本身或指定的默认字符串
|
||||||
|
*/
|
||||||
|
public static String nullToDefault(CharSequence str, String defaultStr) {
|
||||||
|
return (str == null) ? defaultStr : str.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当给定字符串为null时,转换为Empty
|
||||||
|
*
|
||||||
|
* @param str 被转换的字符串
|
||||||
|
* @return 转换后的字符串
|
||||||
|
*/
|
||||||
|
public static String nullToEmpty(CharSequence str) {
|
||||||
|
return nullToDefault(str, EMPTY);
|
||||||
|
}
|
||||||
|
}
|
||||||
232
jodconverter-web/src/main/java/cn/keking/hutool/URLEncoder.java
Normal file
232
jodconverter-web/src/main/java/cn/keking/hutool/URLEncoder.java
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
package cn.keking.hutool;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.BitSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URL编码,数据内容的类型是 application/x-www-form-urlencoded。
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* 1.字符"a"-"z","A"-"Z","0"-"9",".","-","*",和"_" 都不会被编码;
|
||||||
|
* 2.将空格转换为%20 ;
|
||||||
|
* 3.将非文本内容转换成"%xy"的形式,xy是两位16进制的数值;
|
||||||
|
* 4.在每个 name=value 对之间放置 & 符号。
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author looly,
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class URLEncoder implements Serializable{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------------- Static method start
|
||||||
|
/**
|
||||||
|
* 默认{@link URLEncoder}<br>
|
||||||
|
* 默认的编码器针对URI路径编码,定义如下:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* pchar = unreserved(不处理) / pct-encoded / sub-delims(子分隔符) / ":" / "@"
|
||||||
|
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
|
||||||
|
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public static final URLEncoder DEFAULT = createDefault();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于查询语句的{@link URLEncoder}<br>
|
||||||
|
* 编码器针对URI路径编码,定义如下:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* 0x20 ' ' =》 '+'
|
||||||
|
* 0x2A, 0x2D, 0x2E, 0x30 to 0x39, 0x41 to 0x5A, 0x5F, 0x61 to 0x7A as-is
|
||||||
|
* '*', '-', '.', '0' to '9', 'A' to 'Z', '_', 'a' to 'z' Also '=' and '&' 不编码
|
||||||
|
* 其它编码为 %nn 形式
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* 详细见:https://www.w3.org/TR/html5/forms.html#application/x-www-form-urlencoded-encoding-algorithm
|
||||||
|
*/
|
||||||
|
public static final URLEncoder QUERY = createQuery();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建默认{@link URLEncoder}<br>
|
||||||
|
* 默认的编码器针对URI路径编码,定义如下:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* pchar = unreserved(不处理) / pct-encoded / sub-delims(子分隔符) / ":" / "@"
|
||||||
|
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
|
||||||
|
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @return {@link URLEncoder}
|
||||||
|
*/
|
||||||
|
public static URLEncoder createDefault() {
|
||||||
|
final URLEncoder encoder = new URLEncoder();
|
||||||
|
encoder.addSafeCharacter('-');
|
||||||
|
encoder.addSafeCharacter('.');
|
||||||
|
encoder.addSafeCharacter('_');
|
||||||
|
encoder.addSafeCharacter('~');
|
||||||
|
// Add the sub-delims
|
||||||
|
encoder.addSafeCharacter('!');
|
||||||
|
encoder.addSafeCharacter('$');
|
||||||
|
encoder.addSafeCharacter('&');
|
||||||
|
encoder.addSafeCharacter('\'');
|
||||||
|
encoder.addSafeCharacter('(');
|
||||||
|
encoder.addSafeCharacter(')');
|
||||||
|
encoder.addSafeCharacter('*');
|
||||||
|
encoder.addSafeCharacter('+');
|
||||||
|
encoder.addSafeCharacter(',');
|
||||||
|
encoder.addSafeCharacter(';');
|
||||||
|
encoder.addSafeCharacter('=');
|
||||||
|
// Add the remaining literals
|
||||||
|
encoder.addSafeCharacter(':');
|
||||||
|
encoder.addSafeCharacter('@');
|
||||||
|
// Add '/' so it isn't encoded when we encode a path
|
||||||
|
encoder.addSafeCharacter('/');
|
||||||
|
|
||||||
|
return encoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建用于查询语句的{@link URLEncoder}<br>
|
||||||
|
* 编码器针对URI路径编码,定义如下:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* 0x20 ' ' =》 '+'
|
||||||
|
* 0x2A, 0x2D, 0x2E, 0x30 to 0x39, 0x41 to 0x5A, 0x5F, 0x61 to 0x7A as-is
|
||||||
|
* '*', '-', '.', '0' to '9', 'A' to 'Z', '_', 'a' to 'z' Also '=' and '&' 不编码
|
||||||
|
* 其它编码为 %nn 形式
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* 详细见:https://www.w3.org/TR/html5/forms.html#application/x-www-form-urlencoded-encoding-algorithm
|
||||||
|
*
|
||||||
|
* @return {@link URLEncoder}
|
||||||
|
*/
|
||||||
|
public static URLEncoder createQuery() {
|
||||||
|
final URLEncoder encoder = new URLEncoder();
|
||||||
|
// Special encoding for space
|
||||||
|
encoder.setEncodeSpaceAsPlus(true);
|
||||||
|
// Alpha and digit are safe by default
|
||||||
|
// Add the other permitted characters
|
||||||
|
encoder.addSafeCharacter('*');
|
||||||
|
encoder.addSafeCharacter('-');
|
||||||
|
encoder.addSafeCharacter('.');
|
||||||
|
encoder.addSafeCharacter('_');
|
||||||
|
encoder.addSafeCharacter('=');
|
||||||
|
encoder.addSafeCharacter('&');
|
||||||
|
|
||||||
|
return encoder;
|
||||||
|
}
|
||||||
|
// --------------------------------------------------------------------------------------------- Static method end
|
||||||
|
|
||||||
|
/** 存放安全编码 */
|
||||||
|
private final BitSet safeCharacters;
|
||||||
|
/** 是否编码空格为+ */
|
||||||
|
private boolean encodeSpaceAsPlus = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造<br>
|
||||||
|
*
|
||||||
|
* [a-zA-Z0-9]默认不被编码
|
||||||
|
*/
|
||||||
|
public URLEncoder() {
|
||||||
|
this(new BitSet(256));
|
||||||
|
|
||||||
|
for (char i = 'a'; i <= 'z'; i++) {
|
||||||
|
addSafeCharacter(i);
|
||||||
|
}
|
||||||
|
for (char i = 'A'; i <= 'Z'; i++) {
|
||||||
|
addSafeCharacter(i);
|
||||||
|
}
|
||||||
|
for (char i = '0'; i <= '9'; i++) {
|
||||||
|
addSafeCharacter(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param safeCharacters 安全字符,安全字符不被编码
|
||||||
|
*/
|
||||||
|
private URLEncoder(BitSet safeCharacters) {
|
||||||
|
this.safeCharacters = safeCharacters;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 增加安全字符<br>
|
||||||
|
* 安全字符不被编码
|
||||||
|
*
|
||||||
|
* @param c 字符
|
||||||
|
*/
|
||||||
|
public void addSafeCharacter(char c) {
|
||||||
|
safeCharacters.set(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除安全字符<br>
|
||||||
|
* 安全字符不被编码
|
||||||
|
*
|
||||||
|
* @param c 字符
|
||||||
|
*/
|
||||||
|
public void removeSafeCharacter(char c) {
|
||||||
|
safeCharacters.clear(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否将空格编码为+
|
||||||
|
*
|
||||||
|
* @param encodeSpaceAsPlus 是否将空格编码为+
|
||||||
|
*/
|
||||||
|
public void setEncodeSpaceAsPlus(boolean encodeSpaceAsPlus) {
|
||||||
|
this.encodeSpaceAsPlus = encodeSpaceAsPlus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将URL中的字符串编码为%形式
|
||||||
|
*
|
||||||
|
* @param path 需要编码的字符串
|
||||||
|
* @param charset 编码
|
||||||
|
*
|
||||||
|
* @return 编码后的字符串
|
||||||
|
*/
|
||||||
|
public String encode(String path, Charset charset) {
|
||||||
|
|
||||||
|
int maxBytesPerChar = 10;
|
||||||
|
final StringBuilder rewrittenPath = new StringBuilder(path.length());
|
||||||
|
ByteArrayOutputStream buf = new ByteArrayOutputStream(maxBytesPerChar);
|
||||||
|
OutputStreamWriter writer = new OutputStreamWriter(buf, charset);
|
||||||
|
|
||||||
|
int c;
|
||||||
|
for (int i = 0; i < path.length(); i++) {
|
||||||
|
c = path.charAt(i);
|
||||||
|
if (safeCharacters.get(c)) {
|
||||||
|
rewrittenPath.append((char) c);
|
||||||
|
} else if (encodeSpaceAsPlus && c == ' ') {
|
||||||
|
// 对于空格单独处理
|
||||||
|
rewrittenPath.append('+');
|
||||||
|
} else {
|
||||||
|
// convert to external encoding before hex conversion
|
||||||
|
try {
|
||||||
|
writer.write((char) c);
|
||||||
|
writer.flush();
|
||||||
|
} catch (IOException e) {
|
||||||
|
buf.reset();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] ba = buf.toByteArray();
|
||||||
|
for (int j = 0; j < ba.length; j++) {
|
||||||
|
// Converting each byte in the buffer
|
||||||
|
byte toEncode = ba[j];
|
||||||
|
rewrittenPath.append('%');
|
||||||
|
HexUtil.appendHex(rewrittenPath, toEncode, false);
|
||||||
|
}
|
||||||
|
buf.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rewrittenPath.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
74
jodconverter-web/src/main/java/cn/keking/hutool/URLUtil.java
Normal file
74
jodconverter-web/src/main/java/cn/keking/hutool/URLUtil.java
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
package cn.keking.hutool;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统一资源定位符相关工具类
|
||||||
|
*
|
||||||
|
* @author xiaoleilu
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class URLUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标准化URL字符串,包括:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* 1. 多个/替换为一个
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param url URL字符串
|
||||||
|
* @return 标准化后的URL字符串
|
||||||
|
*/
|
||||||
|
public static String normalize(String url) {
|
||||||
|
return normalize(url, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标准化URL字符串,包括:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* 1. 多个/替换为一个
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param url URL字符串
|
||||||
|
* @param isEncodeBody 是否对URL中body部分的中文和特殊字符做转义(不包括http:和/)
|
||||||
|
* @param isEncodeParam 是否对URL中参数部分的中文和特殊字符做转义
|
||||||
|
* @return 标准化后的URL字符串
|
||||||
|
* @since 4.4.1
|
||||||
|
*/
|
||||||
|
public static String normalize(String url, boolean isEncodeBody, boolean isEncodeParam) {
|
||||||
|
if (StrUtil.isBlank(url)) {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
final int sepIndex = url.indexOf("://");
|
||||||
|
String pre;
|
||||||
|
String body;
|
||||||
|
if (sepIndex > 0) {
|
||||||
|
pre = StrUtil.subPre(url, sepIndex + 3);
|
||||||
|
body = StrUtil.subSuf(url, sepIndex + 3);
|
||||||
|
} else {
|
||||||
|
pre = "http://";
|
||||||
|
body = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int paramsSepIndex = StrUtil.indexOf(body, '?');
|
||||||
|
String params = null;
|
||||||
|
if (paramsSepIndex > 0) {
|
||||||
|
params = StrUtil.subSuf(body, paramsSepIndex + 1);
|
||||||
|
body = StrUtil.subPre(body, paramsSepIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 去除开头的\或者/
|
||||||
|
body = body.replaceAll("^[\\\\/]+", StrUtil.EMPTY);
|
||||||
|
// 替换多个\或/为单个/
|
||||||
|
body = body.replace("\\", "/").replaceAll("//+", "/");
|
||||||
|
if (isEncodeBody) {
|
||||||
|
body = URLEncoder.DEFAULT.encode(body, StandardCharsets.UTF_8);
|
||||||
|
if (params != null) {
|
||||||
|
params = "?" + URLEncoder.DEFAULT.encode(params, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pre + body + StrUtil.nullToEmpty(params);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,17 +14,14 @@ public class FileAttribute {
|
|||||||
|
|
||||||
private String url;
|
private String url;
|
||||||
|
|
||||||
private String decodedUrl;
|
|
||||||
|
|
||||||
public FileAttribute() {
|
public FileAttribute() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public FileAttribute(FileType type, String suffix, String name, String url, String decodedUrl) {
|
public FileAttribute(FileType type, String suffix, String name, String url) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.suffix = suffix;
|
this.suffix = suffix;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.url = url;
|
this.url = url;
|
||||||
this.decodedUrl = decodedUrl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public FileType getType() {
|
public FileType getType() {
|
||||||
@@ -58,12 +55,4 @@ public class FileAttribute {
|
|||||||
public void setUrl(String url) {
|
public void setUrl(String url) {
|
||||||
this.url = url;
|
this.url = url;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDecodedUrl() {
|
|
||||||
return decodedUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDecodedUrl(String decodedUrl) {
|
|
||||||
this.decodedUrl = decodedUrl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,9 +11,11 @@ public enum FileType {
|
|||||||
simText("simTextFilePreviewImpl"),
|
simText("simTextFilePreviewImpl"),
|
||||||
pdf("pdfFilePreviewImpl"),
|
pdf("pdfFilePreviewImpl"),
|
||||||
other("otherFilePreviewImpl"),
|
other("otherFilePreviewImpl"),
|
||||||
media("mediaFilePreviewImpl");
|
media("mediaFilePreviewImpl"),
|
||||||
|
cad("cadFilePreviewImpl");
|
||||||
|
|
||||||
|
private final String instanceName;
|
||||||
|
|
||||||
private String instanceName;
|
|
||||||
FileType(String instanceName){
|
FileType(String instanceName){
|
||||||
this.instanceName=instanceName;
|
this.instanceName=instanceName;
|
||||||
}
|
}
|
||||||
@@ -22,7 +24,4 @@ public enum FileType {
|
|||||||
return instanceName;
|
return instanceName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setInstanceName(String instanceName) {
|
|
||||||
this.instanceName = instanceName;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,82 +0,0 @@
|
|||||||
package cn.keking.service;
|
|
||||||
|
|
||||||
import cn.keking.model.FileAttribute;
|
|
||||||
import cn.keking.model.FileType;
|
|
||||||
import cn.keking.service.cache.CacheService;
|
|
||||||
import cn.keking.utils.FileUtils;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.ui.ExtendedModelMap;
|
|
||||||
import javax.annotation.PostConstruct;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by kl on 2018/1/19.
|
|
||||||
* Content :消费队列中的转换文件
|
|
||||||
*/
|
|
||||||
@Service
|
|
||||||
public class FileConverQueueTask {
|
|
||||||
|
|
||||||
Logger logger= LoggerFactory.getLogger(getClass());
|
|
||||||
public static final String queueTaskName="FileConverQueueTask";
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
FilePreviewFactory previewFactory;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
CacheService cacheService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
FileUtils fileUtils;
|
|
||||||
|
|
||||||
@PostConstruct
|
|
||||||
public void startTask(){
|
|
||||||
ExecutorService executorService = Executors.newFixedThreadPool(3);
|
|
||||||
executorService.submit(new ConverTask(previewFactory,cacheService,fileUtils));
|
|
||||||
logger.info("队列处理文件转换任务启动完成 ");
|
|
||||||
}
|
|
||||||
|
|
||||||
class ConverTask implements Runnable{
|
|
||||||
|
|
||||||
FilePreviewFactory previewFactory;
|
|
||||||
|
|
||||||
CacheService cacheService;
|
|
||||||
|
|
||||||
FileUtils fileUtils;
|
|
||||||
|
|
||||||
public ConverTask(FilePreviewFactory previewFactory, CacheService cacheService,FileUtils fileUtils) {
|
|
||||||
this.previewFactory = previewFactory;
|
|
||||||
this.cacheService = cacheService;
|
|
||||||
this.fileUtils=fileUtils;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
while (true) {
|
|
||||||
try {
|
|
||||||
String url = cacheService.takeQueueTask();
|
|
||||||
if(url!=null){
|
|
||||||
FileAttribute fileAttribute=fileUtils.getFileAttribute(url);
|
|
||||||
logger.info("正在处理转换任务,文件名称【{}】",fileAttribute.getName());
|
|
||||||
FileType fileType=fileAttribute.getType();
|
|
||||||
if(fileType.equals(FileType.compress) || fileType.equals(FileType.office)){
|
|
||||||
FilePreview filePreview=previewFactory.get(url);
|
|
||||||
filePreview.filePreviewHandle(url,new ExtendedModelMap());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
try {
|
|
||||||
Thread.sleep(1000*10);
|
|
||||||
}catch (Exception ex){
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
package cn.keking.service;
|
||||||
|
|
||||||
|
import cn.keking.model.FileAttribute;
|
||||||
|
import cn.keking.model.FileType;
|
||||||
|
import cn.keking.service.cache.CacheService;
|
||||||
|
import cn.keking.utils.FileUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.ui.ExtendedModelMap;
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by kl on 2018/1/19.
|
||||||
|
* Content :消费队列中的转换文件
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class FileConvertQueueTask {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
|
private final FilePreviewFactory previewFactory;
|
||||||
|
|
||||||
|
private final CacheService cacheService;
|
||||||
|
|
||||||
|
private final FileUtils fileUtils;
|
||||||
|
|
||||||
|
public FileConvertQueueTask(FilePreviewFactory previewFactory,
|
||||||
|
CacheService cacheService,
|
||||||
|
FileUtils fileUtils) {
|
||||||
|
this.previewFactory = previewFactory;
|
||||||
|
this.cacheService = cacheService;
|
||||||
|
this.fileUtils=fileUtils;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void startTask(){
|
||||||
|
ExecutorService executorService = Executors.newFixedThreadPool(3);
|
||||||
|
executorService.submit(new ConvertTask(previewFactory, cacheService, fileUtils));
|
||||||
|
logger.info("队列处理文件转换任务启动完成 ");
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ConvertTask implements Runnable {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(ConvertTask.class);
|
||||||
|
|
||||||
|
private final FilePreviewFactory previewFactory;
|
||||||
|
|
||||||
|
private final CacheService cacheService;
|
||||||
|
|
||||||
|
private final FileUtils fileUtils;
|
||||||
|
|
||||||
|
public ConvertTask(FilePreviewFactory previewFactory,
|
||||||
|
CacheService cacheService,
|
||||||
|
FileUtils fileUtils) {
|
||||||
|
this.previewFactory = previewFactory;
|
||||||
|
this.cacheService = cacheService;
|
||||||
|
this.fileUtils=fileUtils;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (true) {
|
||||||
|
String url = null;
|
||||||
|
try {
|
||||||
|
url = cacheService.takeQueueTask();
|
||||||
|
if(url != null){
|
||||||
|
FileAttribute fileAttribute = fileUtils.getFileAttribute(url);
|
||||||
|
FileType fileType = fileAttribute.getType();
|
||||||
|
logger.info("正在处理预览转换任务,url:{},预览类型:{}", url, fileType);
|
||||||
|
if(fileType.equals(FileType.compress) || fileType.equals(FileType.office) || fileType.equals(FileType.cad)) {
|
||||||
|
FilePreview filePreview = previewFactory.get(fileAttribute);
|
||||||
|
filePreview.filePreviewHandle(url, new ExtendedModelMap(), fileAttribute);
|
||||||
|
} else {
|
||||||
|
logger.info("预览类型无需处理,url:{},预览类型:{}", url, fileType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000*10);
|
||||||
|
} catch (Exception ex){
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
logger.info("处理预览转换任务异常,url:{}", url, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
package cn.keking.service;
|
package cn.keking.service;
|
||||||
|
|
||||||
import cn.keking.model.FileAttribute;
|
import cn.keking.model.FileAttribute;
|
||||||
import cn.keking.utils.FileUtils;
|
|
||||||
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;
|
||||||
|
|
||||||
@@ -16,15 +13,14 @@ import java.util.Map;
|
|||||||
@Service
|
@Service
|
||||||
public class FilePreviewFactory {
|
public class FilePreviewFactory {
|
||||||
|
|
||||||
@Autowired
|
private final ApplicationContext context;
|
||||||
FileUtils fileUtils;
|
|
||||||
|
|
||||||
@Autowired
|
public FilePreviewFactory(ApplicationContext context) {
|
||||||
ApplicationContext context;
|
this.context = 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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,23 +4,23 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @auther: chenjh
|
* @author: chenjh
|
||||||
* @time: 2019/4/2 16:45
|
* @since: 2019/4/2 16:45
|
||||||
* @description
|
|
||||||
*/
|
*/
|
||||||
public interface CacheService {
|
public interface CacheService {
|
||||||
final String REDIS_FILE_PREVIEW_PDF_KEY = "converted-preview-pdf-file";
|
|
||||||
final String REDIS_FILE_PREVIEW_IMGS_KEY = "converted-preview-imgs-file";//压缩包内图片文件集合
|
|
||||||
final String REDIS_FILE_PREVIEW_PDF_IMGS_KEY = "converted-preview-pdfimgs-file";
|
|
||||||
|
|
||||||
|
String FILE_PREVIEW_PDF_KEY = "converted-preview-pdf-file";
|
||||||
|
String FILE_PREVIEW_IMGS_KEY = "converted-preview-imgs-file";//压缩包内图片文件集合
|
||||||
|
String FILE_PREVIEW_PDF_IMGS_KEY = "converted-preview-pdfimgs-file";
|
||||||
|
String TASK_QUEUE_NAME = "convert-task";
|
||||||
|
|
||||||
final Integer DEFAULT_PDF_CAPACITY = 500000;
|
Integer DEFAULT_PDF_CAPACITY = 500000;
|
||||||
final Integer DEFAULT_IMG_CAPACITY = 500000;
|
Integer DEFAULT_IMG_CAPACITY = 500000;
|
||||||
final Integer DEFAULT_PDFIMG_CAPACITY = 500000;
|
Integer DEFAULT_PDFIMG_CAPACITY = 500000;
|
||||||
|
|
||||||
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();
|
||||||
@@ -29,7 +29,7 @@ public interface CacheService {
|
|||||||
List<String> getImgCache(String key);
|
List<String> getImgCache(String key);
|
||||||
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;
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package cn.keking.service.cache.impl;
|
|||||||
import cn.keking.service.cache.CacheService;
|
import cn.keking.service.cache.CacheService;
|
||||||
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
|
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
|
||||||
import com.googlecode.concurrentlinkedhashmap.Weighers;
|
import com.googlecode.concurrentlinkedhashmap.Weighers;
|
||||||
import org.rocksdb.RocksDB;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@@ -29,7 +28,7 @@ public class CacheServiceJDKImpl implements CacheService {
|
|||||||
|
|
||||||
private static final int QUEUE_SIZE = 500000;
|
private static final int QUEUE_SIZE = 500000;
|
||||||
|
|
||||||
private BlockingQueue blockingQueue = new ArrayBlockingQueue(QUEUE_SIZE);
|
private final BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(QUEUE_SIZE);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initPDFCachePool(Integer capacity) {
|
public void initPDFCachePool(Integer capacity) {
|
||||||
@@ -116,6 +115,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);
|
||||||
@@ -123,6 +129,6 @@ public class CacheServiceJDKImpl implements CacheService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String takeQueueTask() throws InterruptedException {
|
public String takeQueueTask() throws InterruptedException {
|
||||||
return String.valueOf(blockingQueue.take());
|
return blockingQueue.take();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
package cn.keking.service.cache.impl;
|
package cn.keking.service.cache.impl;
|
||||||
|
|
||||||
import cn.keking.service.FileConverQueueTask;
|
|
||||||
import cn.keking.service.cache.CacheService;
|
import cn.keking.service.cache.CacheService;
|
||||||
import org.redisson.Redisson;
|
import org.redisson.Redisson;
|
||||||
import org.redisson.api.RBlockingQueue;
|
import org.redisson.api.RBlockingQueue;
|
||||||
import org.redisson.api.RMapCache;
|
import org.redisson.api.RMapCache;
|
||||||
import org.redisson.api.RedissonClient;
|
import org.redisson.api.RedissonClient;
|
||||||
import org.redisson.config.Config;
|
import org.redisson.config.Config;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@@ -23,16 +21,12 @@ import java.util.Map;
|
|||||||
@Service
|
@Service
|
||||||
public class CacheServiceRedisImpl implements CacheService {
|
public class CacheServiceRedisImpl implements CacheService {
|
||||||
|
|
||||||
private Config config;
|
private final RedissonClient redissonClient;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public CacheServiceRedisImpl(Config config) {
|
public CacheServiceRedisImpl(Config config) {
|
||||||
this.config = config;
|
|
||||||
this.redissonClient = Redisson.create(config);
|
this.redissonClient = Redisson.create(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
private RedissonClient redissonClient;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initPDFCachePool(Integer capacity) {
|
public void initPDFCachePool(Integer capacity) {
|
||||||
|
|
||||||
@@ -50,59 +44,81 @@ public class CacheServiceRedisImpl implements CacheService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void putPDFCache(String key, String value) {
|
public void putPDFCache(String key, String value) {
|
||||||
RMapCache<String, String> convertedList = redissonClient.getMapCache(REDIS_FILE_PREVIEW_PDF_KEY);
|
RMapCache<String, String> convertedList = redissonClient.getMapCache(FILE_PREVIEW_PDF_KEY);
|
||||||
convertedList.fastPut(key, value);
|
convertedList.fastPut(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void putImgCache(String key, List<String> value) {
|
public void putImgCache(String key, List<String> value) {
|
||||||
RMapCache<String, List<String>> convertedList = redissonClient.getMapCache(REDIS_FILE_PREVIEW_IMGS_KEY);
|
RMapCache<String, List<String>> convertedList = redissonClient.getMapCache(FILE_PREVIEW_IMGS_KEY);
|
||||||
convertedList.fastPut(key, value);
|
convertedList.fastPut(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, String> getPDFCache() {
|
public Map<String, String> getPDFCache() {
|
||||||
return redissonClient.getMapCache(REDIS_FILE_PREVIEW_PDF_KEY);
|
return redissonClient.getMapCache(FILE_PREVIEW_PDF_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPDFCache(String key) {
|
public String getPDFCache(String key) {
|
||||||
RMapCache<String, String> convertedList = redissonClient.getMapCache(REDIS_FILE_PREVIEW_PDF_KEY);
|
RMapCache<String, String> convertedList = redissonClient.getMapCache(FILE_PREVIEW_PDF_KEY);
|
||||||
return convertedList.get(key);
|
return convertedList.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, List<String>> getImgCache() {
|
public Map<String, List<String>> getImgCache() {
|
||||||
return redissonClient.getMapCache(REDIS_FILE_PREVIEW_IMGS_KEY);
|
return redissonClient.getMapCache(FILE_PREVIEW_IMGS_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getImgCache(String key) {
|
public List<String> getImgCache(String key) {
|
||||||
RMapCache<String, List<String>> convertedList = redissonClient.getMapCache(REDIS_FILE_PREVIEW_IMGS_KEY);
|
RMapCache<String, List<String>> convertedList = redissonClient.getMapCache(FILE_PREVIEW_IMGS_KEY);
|
||||||
return convertedList.get(key);
|
return convertedList.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Integer getPdfImageCache(String key) {
|
public Integer getPdfImageCache(String key) {
|
||||||
RMapCache<String, Integer> convertedList = redissonClient.getMapCache(REDIS_FILE_PREVIEW_PDF_IMGS_KEY);
|
RMapCache<String, Integer> convertedList = redissonClient.getMapCache(FILE_PREVIEW_PDF_IMGS_KEY);
|
||||||
return convertedList.get(key);
|
return convertedList.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void putPdfImageCache(String pdfFilePath, int num) {
|
public void putPdfImageCache(String pdfFilePath, int num) {
|
||||||
RMapCache<String, Integer> convertedList = redissonClient.getMapCache(REDIS_FILE_PREVIEW_PDF_IMGS_KEY);
|
RMapCache<String, Integer> convertedList = redissonClient.getMapCache(FILE_PREVIEW_PDF_IMGS_KEY);
|
||||||
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(TASK_QUEUE_NAME);
|
||||||
queue.addAsync(url);
|
queue.addAsync(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String takeQueueTask() throws InterruptedException {
|
public String takeQueueTask() throws InterruptedException {
|
||||||
RBlockingQueue<String> queue = redissonClient.getBlockingQueue(FileConverQueueTask.queueTaskName);
|
RBlockingQueue<String> queue = redissonClient.getBlockingQueue(TASK_QUEUE_NAME);
|
||||||
return queue.take();
|
return queue.take();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void cleanPdfCache() {
|
||||||
|
RMapCache<String, String> pdfCache = redissonClient.getMapCache(FILE_PREVIEW_PDF_KEY);
|
||||||
|
pdfCache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cleanImgCache() {
|
||||||
|
RMapCache<String, List<String>> imgCache = redissonClient.getMapCache(FILE_PREVIEW_IMGS_KEY);
|
||||||
|
imgCache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cleanPdfImgCache() {
|
||||||
|
RMapCache<String, Integer> pdfImg = redissonClient.getMapCache(FILE_PREVIEW_PDF_IMGS_KEY);
|
||||||
|
pdfImg.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,24 +36,24 @@ public class CacheServiceRocksDBImpl implements CacheService {
|
|||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(CacheServiceRocksDBImpl.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(CacheServiceRocksDBImpl.class);
|
||||||
|
|
||||||
private BlockingQueue blockingQueue = new ArrayBlockingQueue(QUEUE_SIZE);
|
private final BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(QUEUE_SIZE);
|
||||||
|
|
||||||
private RocksDB db;
|
private RocksDB db;
|
||||||
|
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
db = RocksDB.open(DB_PATH);
|
db = RocksDB.open(DB_PATH);
|
||||||
if (db.get(REDIS_FILE_PREVIEW_PDF_KEY.getBytes()) == null) {
|
if (db.get(FILE_PREVIEW_PDF_KEY.getBytes()) == null) {
|
||||||
Map<String, String> initPDFCache = new HashMap<>();
|
Map<String, String> initPDFCache = new HashMap<>();
|
||||||
db.put(REDIS_FILE_PREVIEW_PDF_KEY.getBytes(), toByteArray(initPDFCache));
|
db.put(FILE_PREVIEW_PDF_KEY.getBytes(), toByteArray(initPDFCache));
|
||||||
}
|
}
|
||||||
if (db.get(REDIS_FILE_PREVIEW_IMGS_KEY.getBytes()) == null) {
|
if (db.get(FILE_PREVIEW_IMGS_KEY.getBytes()) == null) {
|
||||||
Map<String, List<String>> initIMGCache = new HashMap<>();
|
Map<String, List<String>> initIMGCache = new HashMap<>();
|
||||||
db.put(REDIS_FILE_PREVIEW_IMGS_KEY.getBytes(), toByteArray(initIMGCache));
|
db.put(FILE_PREVIEW_IMGS_KEY.getBytes(), toByteArray(initIMGCache));
|
||||||
}
|
}
|
||||||
if (db.get(REDIS_FILE_PREVIEW_PDF_IMGS_KEY.getBytes()) == null) {
|
if (db.get(FILE_PREVIEW_PDF_IMGS_KEY.getBytes()) == null) {
|
||||||
Map<String, Integer> initPDFIMGCache = new HashMap<>();
|
Map<String, Integer> initPDFIMGCache = new HashMap<>();
|
||||||
db.put(REDIS_FILE_PREVIEW_PDF_IMGS_KEY.getBytes(), toByteArray(initPDFIMGCache));
|
db.put(FILE_PREVIEW_PDF_IMGS_KEY.getBytes(), toByteArray(initPDFIMGCache));
|
||||||
}
|
}
|
||||||
} catch (RocksDBException | IOException e) {
|
} catch (RocksDBException | IOException e) {
|
||||||
LOGGER.error("Uable to init RocksDB" + e);
|
LOGGER.error("Uable to init RocksDB" + e);
|
||||||
@@ -79,9 +79,9 @@ public class CacheServiceRocksDBImpl implements CacheService {
|
|||||||
@Override
|
@Override
|
||||||
public void putPDFCache(String key, String value) {
|
public void putPDFCache(String key, String value) {
|
||||||
try {
|
try {
|
||||||
Map<String, String> pdfCacheItem = new HashMap<>();
|
Map<String, String> pdfCacheItem = getPDFCache();
|
||||||
pdfCacheItem.put(key, value);
|
pdfCacheItem.put(key, value);
|
||||||
db.put(REDIS_FILE_PREVIEW_PDF_KEY.getBytes(), toByteArray(pdfCacheItem));
|
db.put(FILE_PREVIEW_PDF_KEY.getBytes(), toByteArray(pdfCacheItem));
|
||||||
} catch (RocksDBException | IOException e) {
|
} catch (RocksDBException | IOException e) {
|
||||||
LOGGER.error("Put into RocksDB Exception" + e);
|
LOGGER.error("Put into RocksDB Exception" + e);
|
||||||
}
|
}
|
||||||
@@ -90,19 +90,20 @@ public class CacheServiceRocksDBImpl implements CacheService {
|
|||||||
@Override
|
@Override
|
||||||
public void putImgCache(String key, List<String> value) {
|
public void putImgCache(String key, List<String> value) {
|
||||||
try {
|
try {
|
||||||
Map<String, List<String>> imgCacheItem = new HashMap<>();
|
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(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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public Map<String, String> getPDFCache() {
|
public Map<String, String> getPDFCache() {
|
||||||
Map<String, String> result = new HashMap<>();
|
Map<String, String> result = new HashMap<>();
|
||||||
try{
|
try{
|
||||||
result = (Map<String, String>) toObject(db.get(REDIS_FILE_PREVIEW_PDF_KEY.getBytes()));
|
result = (Map<String, String>) toObject(db.get(FILE_PREVIEW_PDF_KEY.getBytes()));
|
||||||
} catch (RocksDBException | IOException | ClassNotFoundException e) {
|
} catch (RocksDBException | IOException | ClassNotFoundException e) {
|
||||||
LOGGER.error("Get from RocksDB Exception" + e);
|
LOGGER.error("Get from RocksDB Exception" + e);
|
||||||
}
|
}
|
||||||
@@ -110,10 +111,11 @@ public class CacheServiceRocksDBImpl implements CacheService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public String getPDFCache(String key) {
|
public String getPDFCache(String key) {
|
||||||
String result = "";
|
String result = "";
|
||||||
try{
|
try{
|
||||||
Map<String, String> map = (Map<String, String>) toObject(db.get(REDIS_FILE_PREVIEW_PDF_KEY.getBytes()));
|
Map<String, String> map = (Map<String, String>) toObject(db.get(FILE_PREVIEW_PDF_KEY.getBytes()));
|
||||||
result = map.get(key);
|
result = map.get(key);
|
||||||
} catch (RocksDBException | IOException | ClassNotFoundException e) {
|
} catch (RocksDBException | IOException | ClassNotFoundException e) {
|
||||||
LOGGER.error("Get from RocksDB Exception" + e);
|
LOGGER.error("Get from RocksDB Exception" + e);
|
||||||
@@ -122,10 +124,11 @@ public class CacheServiceRocksDBImpl implements CacheService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public Map<String, List<String>> getImgCache() {
|
public Map<String, List<String>> getImgCache() {
|
||||||
Map<String, List<String>> result = new HashMap<>();
|
Map<String, List<String>> result = new HashMap<>();
|
||||||
try{
|
try{
|
||||||
result = (Map<String, List<String>>) toObject(db.get(REDIS_FILE_PREVIEW_IMGS_KEY.getBytes()));
|
result = (Map<String, List<String>>) toObject(db.get(FILE_PREVIEW_IMGS_KEY.getBytes()));
|
||||||
} catch (RocksDBException | IOException | ClassNotFoundException e) {
|
} catch (RocksDBException | IOException | ClassNotFoundException e) {
|
||||||
LOGGER.error("Get from RocksDB Exception" + e);
|
LOGGER.error("Get from RocksDB Exception" + e);
|
||||||
}
|
}
|
||||||
@@ -133,11 +136,12 @@ public class CacheServiceRocksDBImpl implements CacheService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public List<String> getImgCache(String key) {
|
public List<String> getImgCache(String key) {
|
||||||
List<String> result = new ArrayList<>();
|
List<String> result = new ArrayList<>();
|
||||||
Map<String, List<String>> map;
|
Map<String, List<String>> map;
|
||||||
try{
|
try{
|
||||||
map = (Map<String, List<String>>) toObject(db.get(REDIS_FILE_PREVIEW_IMGS_KEY.getBytes()));
|
map = (Map<String, List<String>>) toObject(db.get(FILE_PREVIEW_IMGS_KEY.getBytes()));
|
||||||
result = map.get(key);
|
result = map.get(key);
|
||||||
} catch (RocksDBException | IOException | ClassNotFoundException e) {
|
} catch (RocksDBException | IOException | ClassNotFoundException e) {
|
||||||
LOGGER.error("Get from RocksDB Exception" + e);
|
LOGGER.error("Get from RocksDB Exception" + e);
|
||||||
@@ -146,11 +150,12 @@ public class CacheServiceRocksDBImpl implements CacheService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public Integer getPdfImageCache(String key) {
|
public Integer getPdfImageCache(String key) {
|
||||||
Integer result = 0;
|
Integer result = 0;
|
||||||
Map<String, Integer> map;
|
Map<String, Integer> map;
|
||||||
try{
|
try{
|
||||||
map = (Map<String, Integer>) toObject(db.get(REDIS_FILE_PREVIEW_PDF_IMGS_KEY.getBytes()));
|
map = (Map<String, Integer>) toObject(db.get(FILE_PREVIEW_PDF_IMGS_KEY.getBytes()));
|
||||||
result = map.get(key);
|
result = map.get(key);
|
||||||
} catch (RocksDBException | IOException | ClassNotFoundException e) {
|
} catch (RocksDBException | IOException | ClassNotFoundException e) {
|
||||||
LOGGER.error("Get from RocksDB Exception" + e);
|
LOGGER.error("Get from RocksDB Exception" + e);
|
||||||
@@ -161,14 +166,25 @@ public class CacheServiceRocksDBImpl implements CacheService {
|
|||||||
@Override
|
@Override
|
||||||
public void putPdfImageCache(String pdfFilePath, int num) {
|
public void putPdfImageCache(String pdfFilePath, int num) {
|
||||||
try {
|
try {
|
||||||
Map<String, Integer> pdfImageCacheItem = new HashMap<>();
|
Map<String, Integer> pdfImageCacheItem = getPdfImageCaches();
|
||||||
pdfImageCacheItem.put(pdfFilePath, num);
|
pdfImageCacheItem.put(pdfFilePath, num);
|
||||||
db.put(REDIS_FILE_PREVIEW_PDF_IMGS_KEY.getBytes(), toByteArray(pdfImageCacheItem));
|
db.put(FILE_PREVIEW_PDF_IMGS_KEY.getBytes(), toByteArray(pdfImageCacheItem));
|
||||||
} catch (RocksDBException | IOException e) {
|
} catch (RocksDBException | IOException e) {
|
||||||
LOGGER.error("Put into RocksDB Exception" + e);
|
LOGGER.error("Put into RocksDB Exception" + e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
@@ -176,11 +192,23 @@ public class CacheServiceRocksDBImpl implements CacheService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String takeQueueTask() throws InterruptedException {
|
public String takeQueueTask() throws InterruptedException {
|
||||||
return String.valueOf(blockingQueue.take());
|
return blockingQueue.take();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private Map<String, Integer> getPdfImageCaches() {
|
||||||
|
Map<String, Integer> map = new HashMap<>();
|
||||||
|
try{
|
||||||
|
map = (Map<String, Integer>) toObject(db.get(FILE_PREVIEW_PDF_IMGS_KEY.getBytes()));
|
||||||
|
} catch (RocksDBException | IOException | ClassNotFoundException e) {
|
||||||
|
LOGGER.error("Get from RocksDB Exception" + e);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private byte[] toByteArray (Object obj) throws IOException {
|
private byte[] toByteArray (Object obj) throws IOException {
|
||||||
byte[] bytes = null;
|
byte[] bytes;
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
ObjectOutputStream oos = new ObjectOutputStream(bos);
|
ObjectOutputStream oos = new ObjectOutputStream(bos);
|
||||||
oos.writeObject(obj);
|
oos.writeObject(obj);
|
||||||
@@ -192,7 +220,7 @@ public class CacheServiceRocksDBImpl implements CacheService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Object toObject (byte[] bytes) throws IOException, ClassNotFoundException {
|
private Object toObject (byte[] bytes) throws IOException, ClassNotFoundException {
|
||||||
Object obj = null;
|
Object obj;
|
||||||
ByteArrayInputStream bis = new ByteArrayInputStream (bytes);
|
ByteArrayInputStream bis = new ByteArrayInputStream (bytes);
|
||||||
ObjectInputStream ois = new ObjectInputStream (bis);
|
ObjectInputStream ois = new ObjectInputStream (bis);
|
||||||
obj = ois.readObject();
|
obj = ois.readObject();
|
||||||
@@ -200,4 +228,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(FILE_PREVIEW_PDF_KEY.getBytes(), toByteArray(initPDFCache));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cleanImgCache() throws IOException, RocksDBException {
|
||||||
|
Map<String, List<String>> initIMGCache = new HashMap<>();
|
||||||
|
db.put(FILE_PREVIEW_IMGS_KEY.getBytes(), toByteArray(initIMGCache));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cleanPdfImgCache() throws IOException, RocksDBException {
|
||||||
|
Map<String, Integer> initPDFIMGCache = new HashMap<>();
|
||||||
|
db.put(FILE_PREVIEW_PDF_IMGS_KEY.getBytes(), toByteArray(initPDFIMGCache));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,89 @@
|
|||||||
|
package cn.keking.service.impl;
|
||||||
|
|
||||||
|
import cn.keking.config.ConfigConstants;
|
||||||
|
import cn.keking.model.FileAttribute;
|
||||||
|
import cn.keking.model.ReturnResponse;
|
||||||
|
import cn.keking.service.FilePreview;
|
||||||
|
import cn.keking.utils.CadUtils;
|
||||||
|
import cn.keking.utils.DownloadUtils;
|
||||||
|
import cn.keking.utils.FileUtils;
|
||||||
|
import cn.keking.utils.PdfUtils;
|
||||||
|
import cn.keking.web.filter.BaseUrlFilter;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.ui.Model;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import static cn.keking.service.impl.OfficeFilePreviewImpl.getPreviewType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author chenjh
|
||||||
|
* @since 2019/11/21 14:28
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class CadFilePreviewImpl implements FilePreview {
|
||||||
|
|
||||||
|
private final FileUtils fileUtils;
|
||||||
|
|
||||||
|
private final DownloadUtils downloadUtils;
|
||||||
|
|
||||||
|
private final CadUtils cadUtils;
|
||||||
|
|
||||||
|
private final PdfUtils pdfUtils;
|
||||||
|
|
||||||
|
public CadFilePreviewImpl(FileUtils fileUtils,
|
||||||
|
DownloadUtils downloadUtils,
|
||||||
|
CadUtils cadUtils,
|
||||||
|
PdfUtils pdfUtils) {
|
||||||
|
this.fileUtils = fileUtils;
|
||||||
|
this.downloadUtils = downloadUtils;
|
||||||
|
this.cadUtils = cadUtils;
|
||||||
|
this.pdfUtils = pdfUtils;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String OFFICE_PREVIEW_TYPE_IMAGE = "image";
|
||||||
|
private static final String OFFICE_PREVIEW_TYPE_ALL_IMAGES = "allImages";
|
||||||
|
private static final String FILE_DIR = ConfigConstants.getFileDir();
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
|
||||||
|
// 预览Type,参数传了就取参数的,没传取系统默认
|
||||||
|
String officePreviewType = model.asMap().get("officePreviewType") == null ? ConfigConstants.getOfficePreviewType() : model.asMap().get("officePreviewType").toString();
|
||||||
|
String baseUrl = BaseUrlFilter.getBaseUrl();
|
||||||
|
String suffix=fileAttribute.getSuffix();
|
||||||
|
String fileName=fileAttribute.getName();
|
||||||
|
String pdfName = fileName.substring(0, fileName.lastIndexOf(".") + 1) + "pdf";
|
||||||
|
String outFilePath = FILE_DIR + pdfName;
|
||||||
|
// 判断之前是否已转换过,如果转换过,直接返回,否则执行转换
|
||||||
|
if (!fileUtils.listConvertedFiles().containsKey(pdfName) || !ConfigConstants.isCacheEnabled()) {
|
||||||
|
String filePath;
|
||||||
|
ReturnResponse<String> response = downloadUtils.downLoad(fileAttribute, null);
|
||||||
|
if (0 != response.getCode()) {
|
||||||
|
model.addAttribute("fileType", suffix);
|
||||||
|
model.addAttribute("msg", response.getMsg());
|
||||||
|
return "fileNotSupported";
|
||||||
|
}
|
||||||
|
filePath = response.getContent();
|
||||||
|
if (StringUtils.hasText(outFilePath)) {
|
||||||
|
boolean convertResult = cadUtils.cadToPdf(filePath, outFilePath);
|
||||||
|
if (!convertResult) {
|
||||||
|
model.addAttribute("fileType", suffix);
|
||||||
|
model.addAttribute("msg", "cad文件转换异常,请联系管理员");
|
||||||
|
return "fileNotSupported";
|
||||||
|
}
|
||||||
|
if (ConfigConstants.isCacheEnabled()) {
|
||||||
|
// 加入缓存
|
||||||
|
fileUtils.addConvertedFile(pdfName, fileUtils.getRelativePath(outFilePath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (baseUrl != null && (OFFICE_PREVIEW_TYPE_IMAGE.equals(officePreviewType) || OFFICE_PREVIEW_TYPE_ALL_IMAGES.equals(officePreviewType))) {
|
||||||
|
return getPreviewType(model, fileAttribute, officePreviewType, baseUrl, pdfName, outFilePath, pdfUtils, OFFICE_PREVIEW_TYPE_IMAGE);
|
||||||
|
}
|
||||||
|
model.addAttribute("pdfUrl", pdfName);
|
||||||
|
return "pdf";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
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;
|
||||||
import cn.keking.utils.DownloadUtils;
|
import cn.keking.utils.DownloadUtils;
|
||||||
import cn.keking.utils.FileUtils;
|
import cn.keking.utils.FileUtils;
|
||||||
import cn.keking.utils.ZipReader;
|
import cn.keking.utils.ZipReader;
|
||||||
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 org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
@@ -16,27 +16,30 @@ import org.springframework.util.StringUtils;
|
|||||||
* Content :处理压缩包文件
|
* Content :处理压缩包文件
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class CompressFilePreviewImpl implements FilePreview{
|
public class CompressFilePreviewImpl implements FilePreview {
|
||||||
|
|
||||||
@Autowired
|
private final FileUtils fileUtils;
|
||||||
FileUtils fileUtils;
|
|
||||||
|
|
||||||
@Autowired
|
private final DownloadUtils downloadUtils;
|
||||||
DownloadUtils downloadUtils;
|
|
||||||
|
|
||||||
@Autowired
|
private final ZipReader zipReader;
|
||||||
ZipReader zipReader;
|
|
||||||
|
public CompressFilePreviewImpl(FileUtils fileUtils,
|
||||||
|
DownloadUtils downloadUtils,
|
||||||
|
ZipReader zipReader) {
|
||||||
|
this.fileUtils = fileUtils;
|
||||||
|
this.downloadUtils = downloadUtils;
|
||||||
|
this.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());
|
||||||
@@ -47,8 +50,10 @@ public class CompressFilePreviewImpl implements FilePreview{
|
|||||||
fileTree = zipReader.readZipFile(filePath, fileName);
|
fileTree = zipReader.readZipFile(filePath, fileName);
|
||||||
} else if ("rar".equalsIgnoreCase(suffix)) {
|
} else if ("rar".equalsIgnoreCase(suffix)) {
|
||||||
fileTree = zipReader.unRar(filePath, fileName);
|
fileTree = zipReader.unRar(filePath, fileName);
|
||||||
|
} else if ("7z".equalsIgnoreCase(suffix)) {
|
||||||
|
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 {
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
package cn.keking.service.impl;
|
package cn.keking.service.impl;
|
||||||
|
|
||||||
|
import cn.keking.model.FileAttribute;
|
||||||
|
import cn.keking.model.ReturnResponse;
|
||||||
import cn.keking.service.FilePreview;
|
import cn.keking.service.FilePreview;
|
||||||
|
import cn.keking.utils.DownloadUtils;
|
||||||
import cn.keking.utils.FileUtils;
|
import cn.keking.utils.FileUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import cn.keking.web.filter.BaseUrlFilter;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
/**
|
/**
|
||||||
@@ -14,12 +17,36 @@ import org.springframework.ui.Model;
|
|||||||
@Service
|
@Service
|
||||||
public class MediaFilePreviewImpl implements FilePreview {
|
public class MediaFilePreviewImpl implements FilePreview {
|
||||||
|
|
||||||
@Autowired
|
private final DownloadUtils downloadUtils;
|
||||||
FileUtils fileUtils;
|
|
||||||
|
private final FileUtils fileUtils;
|
||||||
|
|
||||||
|
public MediaFilePreviewImpl(DownloadUtils downloadUtils,
|
||||||
|
FileUtils fileUtils) {
|
||||||
|
this.downloadUtils = downloadUtils;
|
||||||
|
this.fileUtils = fileUtils;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String filePreviewHandle(String url, Model model) {
|
public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
|
||||||
|
// 不是http开头,浏览器不能直接访问,需下载到本地
|
||||||
|
if (url != null && !url.toLowerCase().startsWith("http")) {
|
||||||
|
ReturnResponse<String> response = downloadUtils.downLoad(fileAttribute, fileAttribute.getName());
|
||||||
|
if (0 != response.getCode()) {
|
||||||
|
model.addAttribute("fileType", fileAttribute.getSuffix());
|
||||||
|
model.addAttribute("msg", response.getMsg());
|
||||||
|
return "fileNotSupported";
|
||||||
|
} else {
|
||||||
|
model.addAttribute("mediaUrl", BaseUrlFilter.getBaseUrl() + fileUtils.getRelativePath(response.getContent()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
model.addAttribute("mediaUrl", url);
|
||||||
|
}
|
||||||
model.addAttribute("mediaUrl", url);
|
model.addAttribute("mediaUrl", url);
|
||||||
|
String suffix=fileAttribute.getSuffix();
|
||||||
|
if ("flv".equalsIgnoreCase(suffix)) {
|
||||||
|
return "flv";
|
||||||
|
}
|
||||||
return "media";
|
return "media";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,14 +8,11 @@ import cn.keking.utils.DownloadUtils;
|
|||||||
import cn.keking.utils.FileUtils;
|
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 cn.keking.web.filter.BaseUrlFilter;
|
||||||
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;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -25,78 +22,80 @@ import java.util.List;
|
|||||||
@Service
|
@Service
|
||||||
public class OfficeFilePreviewImpl implements FilePreview {
|
public class OfficeFilePreviewImpl implements FilePreview {
|
||||||
|
|
||||||
@Autowired
|
private final FileUtils fileUtils;
|
||||||
FileUtils fileUtils;
|
|
||||||
|
|
||||||
@Autowired
|
private final PdfUtils pdfUtils;
|
||||||
PdfUtils pdfUtils;
|
|
||||||
|
|
||||||
@Autowired
|
private final DownloadUtils downloadUtils;
|
||||||
DownloadUtils downloadUtils;
|
|
||||||
|
|
||||||
@Autowired
|
private final OfficeToPdf officeToPdf;
|
||||||
private OfficeToPdf officeToPdf;
|
|
||||||
|
|
||||||
String fileDir = ConfigConstants.getFileDir();
|
public OfficeFilePreviewImpl(FileUtils fileUtils,
|
||||||
|
PdfUtils pdfUtils,
|
||||||
|
DownloadUtils downloadUtils,
|
||||||
|
OfficeToPdf officeToPdf) {
|
||||||
|
this.fileUtils = fileUtils;
|
||||||
|
this.pdfUtils = pdfUtils;
|
||||||
|
this.downloadUtils = downloadUtils;
|
||||||
|
this.officeToPdf = officeToPdf;
|
||||||
|
}
|
||||||
|
|
||||||
public static final String OFFICE_PREVIEW_TYPE_PDF = "pdf";
|
|
||||||
public static final String OFFICE_PREVIEW_TYPE_IMAGE = "image";
|
public static final String OFFICE_PREVIEW_TYPE_IMAGE = "image";
|
||||||
public static final String OFFICE_PREVIEW_TYPE_ALLIMAGES = "allImages";
|
public static final String OFFICE_PREVIEW_TYPE_ALL_IMAGES = "allImages";
|
||||||
|
private static final String FILE_DIR = ConfigConstants.getFileDir();
|
||||||
|
|
||||||
@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 baseUrl = BaseUrlFilter.getBaseUrl();
|
||||||
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 = FILE_DIR + pdfName;
|
||||||
// 判断之前是否已转换过,如果转换过,直接返回,否则执行转换
|
// 判断之前是否已转换过,如果转换过,直接返回,否则执行转换
|
||||||
if (!fileUtils.listConvertedFiles().containsKey(pdfName)) {
|
if (!fileUtils.listConvertedFiles().containsKey(pdfName) || !ConfigConstants.isCacheEnabled()) {
|
||||||
String filePath = fileDir + fileName;
|
String filePath;
|
||||||
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 && baseUrl != null && (OFFICE_PREVIEW_TYPE_IMAGE.equals(officePreviewType) || OFFICE_PREVIEW_TYPE_ALL_IMAGES.equals(officePreviewType))) {
|
||||||
List<String> imageUrls = pdfUtils.pdf2jpg(outFilePath, pdfName, originUrl);
|
return getPreviewType(model, fileAttribute, officePreviewType, baseUrl, pdfName, outFilePath, pdfUtils, OFFICE_PREVIEW_TYPE_IMAGE);
|
||||||
if (imageUrls == null || imageUrls.size() < 1) {
|
|
||||||
model.addAttribute("msg", "office转图片异常,请联系管理员");
|
|
||||||
model.addAttribute("fileType",fileAttribute.getSuffix());
|
|
||||||
return "fileNotSupported";
|
|
||||||
}
|
|
||||||
model.addAttribute("imgurls", imageUrls);
|
|
||||||
model.addAttribute("currentUrl", imageUrls.get(0));
|
|
||||||
if (OFFICE_PREVIEW_TYPE_IMAGE.equals(officePreviewType)) {
|
|
||||||
return "officePicture";
|
|
||||||
} else {
|
|
||||||
return "picture";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
model.addAttribute("pdfUrl", pdfName);
|
model.addAttribute("pdfUrl", pdfName);
|
||||||
return isHtml ? "html" : "pdf";
|
return isHtml ? "html" : "pdf";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static String getPreviewType(Model model, FileAttribute fileAttribute, String officePreviewType, String baseUrl, String pdfName, String outFilePath, PdfUtils pdfUtils, String officePreviewTypeImage) {
|
||||||
|
List<String> imageUrls = pdfUtils.pdf2jpg(outFilePath, pdfName, baseUrl);
|
||||||
|
if (imageUrls == null || imageUrls.size() < 1) {
|
||||||
|
model.addAttribute("msg", "office转图片异常,请联系管理员");
|
||||||
|
model.addAttribute("fileType",fileAttribute.getSuffix());
|
||||||
|
return "fileNotSupported";
|
||||||
|
}
|
||||||
|
model.addAttribute("imgurls", imageUrls);
|
||||||
|
model.addAttribute("currentUrl", imageUrls.get(0));
|
||||||
|
if (officePreviewTypeImage.equals(officePreviewType)) {
|
||||||
|
return "officePicture";
|
||||||
|
} else {
|
||||||
|
return "picture";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ package cn.keking.service.impl;
|
|||||||
|
|
||||||
import cn.keking.model.FileAttribute;
|
import cn.keking.model.FileAttribute;
|
||||||
import cn.keking.service.FilePreview;
|
import cn.keking.service.FilePreview;
|
||||||
import cn.keking.utils.FileUtils;
|
|
||||||
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;
|
||||||
|
|
||||||
@@ -13,16 +11,10 @@ import org.springframework.ui.Model;
|
|||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class OtherFilePreviewImpl implements FilePreview {
|
public class OtherFilePreviewImpl implements FilePreview {
|
||||||
@Autowired
|
|
||||||
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", "系统还不支持该格式文件的在线预览");
|
||||||
"如有需要请按下方显示的邮箱地址联系系统维护人员");
|
|
||||||
return "fileNotSupported";
|
return "fileNotSupported";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,11 +7,10 @@ import cn.keking.service.FilePreview;
|
|||||||
import cn.keking.utils.DownloadUtils;
|
import cn.keking.utils.DownloadUtils;
|
||||||
import cn.keking.utils.FileUtils;
|
import cn.keking.utils.FileUtils;
|
||||||
import cn.keking.utils.PdfUtils;
|
import cn.keking.utils.PdfUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import cn.keking.web.filter.BaseUrlFilter;
|
||||||
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.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -19,43 +18,48 @@ import java.util.List;
|
|||||||
* Content :处理pdf文件
|
* Content :处理pdf文件
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class PdfFilePreviewImpl implements FilePreview{
|
public class PdfFilePreviewImpl implements FilePreview {
|
||||||
|
|
||||||
|
private final FileUtils fileUtils;
|
||||||
|
|
||||||
@Autowired
|
private final PdfUtils pdfUtils;
|
||||||
FileUtils fileUtils;
|
|
||||||
|
|
||||||
@Autowired
|
private final DownloadUtils downloadUtils;
|
||||||
PdfUtils pdfUtils;
|
|
||||||
|
|
||||||
@Autowired
|
private static final String FILE_DIR = ConfigConstants.getFileDir();
|
||||||
DownloadUtils downloadUtils;
|
|
||||||
|
|
||||||
String fileDir = ConfigConstants.getFileDir();
|
public PdfFilePreviewImpl(FileUtils fileUtils,
|
||||||
|
PdfUtils pdfUtils,
|
||||||
|
DownloadUtils downloadUtils) {
|
||||||
|
this.fileUtils = fileUtils;
|
||||||
|
this.pdfUtils = pdfUtils;
|
||||||
|
this.downloadUtils = downloadUtils;
|
||||||
|
}
|
||||||
|
|
||||||
@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 ? "" : 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 baseUrl = BaseUrlFilter.getBaseUrl();
|
||||||
model.addAttribute("pdfUrl", url);
|
|
||||||
String pdfName = fileName.substring(0, fileName.lastIndexOf(".") + 1) + "pdf";
|
String pdfName = fileName.substring(0, fileName.lastIndexOf(".") + 1) + "pdf";
|
||||||
String outFilePath = fileDir + pdfName;
|
String outFilePath = FILE_DIR + 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_ALL_IMAGES.equals(officePreviewType)) {
|
||||||
//当文件不存在时,就去下载
|
//当文件不存在时,就去下载
|
||||||
if (!new File(outFilePath).exists()) {
|
if (!fileUtils.listConvertedFiles().containsKey(pdfName) || !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());
|
||||||
return "fileNotSupported";
|
return "fileNotSupported";
|
||||||
}
|
}
|
||||||
outFilePath = response.getContent();
|
outFilePath = response.getContent();
|
||||||
|
if (ConfigConstants.isCacheEnabled()) {
|
||||||
|
// 加入缓存
|
||||||
|
fileUtils.addConvertedFile(pdfName, fileUtils.getRelativePath(outFilePath));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
List<String> imageUrls = pdfUtils.pdf2jpg(outFilePath, pdfName, originUrl);
|
List<String> imageUrls = pdfUtils.pdf2jpg(outFilePath, pdfName, baseUrl);
|
||||||
if (imageUrls == null || imageUrls.size() < 1) {
|
if (imageUrls == null || imageUrls.size() < 1) {
|
||||||
model.addAttribute("msg", "pdf转图片异常,请联系管理员");
|
model.addAttribute("msg", "pdf转图片异常,请联系管理员");
|
||||||
model.addAttribute("fileType",fileAttribute.getSuffix());
|
model.addAttribute("fileType",fileAttribute.getSuffix());
|
||||||
@@ -68,6 +72,27 @@ public class PdfFilePreviewImpl implements FilePreview{
|
|||||||
} else {
|
} else {
|
||||||
return "picture";
|
return "picture";
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// 不是http开头,浏览器不能直接访问,需下载到本地
|
||||||
|
if (url != null && !url.toLowerCase().startsWith("http")) {
|
||||||
|
if (!fileUtils.listConvertedFiles().containsKey(pdfName) || !ConfigConstants.isCacheEnabled()) {
|
||||||
|
ReturnResponse<String> response = downloadUtils.downLoad(fileAttribute, pdfName);
|
||||||
|
if (0 != response.getCode()) {
|
||||||
|
model.addAttribute("fileType", suffix);
|
||||||
|
model.addAttribute("msg", response.getMsg());
|
||||||
|
return "fileNotSupported";
|
||||||
|
}
|
||||||
|
model.addAttribute("pdfUrl", fileUtils.getRelativePath(response.getContent()));
|
||||||
|
if (ConfigConstants.isCacheEnabled()) {
|
||||||
|
// 加入缓存
|
||||||
|
fileUtils.addConvertedFile(pdfName, fileUtils.getRelativePath(outFilePath));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
model.addAttribute("pdfUrl", pdfName);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
model.addAttribute("pdfUrl", url);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return "pdf";
|
return "pdf";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
package cn.keking.service.impl;
|
package cn.keking.service.impl;
|
||||||
|
|
||||||
|
import cn.keking.model.FileAttribute;
|
||||||
|
import cn.keking.model.ReturnResponse;
|
||||||
import cn.keking.service.FilePreview;
|
import cn.keking.service.FilePreview;
|
||||||
|
import cn.keking.utils.DownloadUtils;
|
||||||
import cn.keking.utils.FileUtils;
|
import cn.keking.utils.FileUtils;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
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 org.springframework.web.context.request.RequestContextHolder;
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
@@ -17,21 +19,42 @@ import java.util.List;
|
|||||||
@Service
|
@Service
|
||||||
public class PictureFilePreviewImpl implements FilePreview {
|
public class PictureFilePreviewImpl implements FilePreview {
|
||||||
|
|
||||||
@Autowired
|
private final FileUtils fileUtils;
|
||||||
FileUtils fileUtils;
|
|
||||||
|
private final DownloadUtils downloadUtils;
|
||||||
|
|
||||||
|
public PictureFilePreviewImpl(FileUtils fileUtils,
|
||||||
|
DownloadUtils downloadUtils) {
|
||||||
|
this.fileUtils = fileUtils;
|
||||||
|
this.downloadUtils = downloadUtils;
|
||||||
|
}
|
||||||
|
|
||||||
@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<String> imgUrls = Lists.newArrayList(url);
|
||||||
try{
|
try {
|
||||||
imgUrls.clear();
|
imgUrls.clear();
|
||||||
imgUrls.addAll(fileUtils.getRedisImgUrls(fileKey));
|
imgUrls.addAll(fileUtils.getImgCache(fileKey));
|
||||||
}catch (Exception e){
|
} catch (Exception e){
|
||||||
imgUrls = Lists.newArrayList(url);
|
imgUrls = Lists.newArrayList(url);
|
||||||
}
|
}
|
||||||
model.addAttribute("imgurls", imgUrls);
|
// 不是http开头,浏览器不能直接访问,需下载到本地
|
||||||
model.addAttribute("currentUrl",url);
|
if (url != null && !url.toLowerCase().startsWith("http")) {
|
||||||
|
ReturnResponse<String> response = downloadUtils.downLoad(fileAttribute, null);
|
||||||
|
if (0 != response.getCode()) {
|
||||||
|
model.addAttribute("fileType", fileAttribute.getSuffix());
|
||||||
|
model.addAttribute("msg", response.getMsg());
|
||||||
|
return "fileNotSupported";
|
||||||
|
} else {
|
||||||
|
String file = fileUtils.getRelativePath(response.getContent());
|
||||||
|
model.addAttribute("imgurls", Lists.newArrayList(file));
|
||||||
|
model.addAttribute("currentUrl", file);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
model.addAttribute("imgurls", imgUrls);
|
||||||
|
model.addAttribute("currentUrl", url);
|
||||||
|
}
|
||||||
return "picture";
|
return "picture";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,36 +3,48 @@ package cn.keking.service.impl;
|
|||||||
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;
|
||||||
import cn.keking.utils.FileUtils;
|
import cn.keking.utils.DownloadUtils;
|
||||||
import cn.keking.utils.SimTextUtil;
|
|
||||||
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 :处理文本文件
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class SimTextFilePreviewImpl implements FilePreview{
|
public class SimTextFilePreviewImpl implements FilePreview {
|
||||||
|
|
||||||
@Autowired
|
private final DownloadUtils downloadUtils;
|
||||||
SimTextUtil simTextUtil;
|
|
||||||
|
|
||||||
@Autowired
|
public SimTextFilePreviewImpl(DownloadUtils downloadUtils) {
|
||||||
FileUtils fileUtils;
|
this.downloadUtils = downloadUtils;
|
||||||
|
}
|
||||||
|
|
||||||
@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 decodedUrl=fileAttribute.getDecodedUrl();
|
ReturnResponse<String> response = downloadUtils.downLoad(fileAttribute, fileName);
|
||||||
String fileName=fileAttribute.getName();
|
|
||||||
ReturnResponse<String> response = simTextUtil.readSimText(decodedUrl, fileName);
|
|
||||||
if (0 != response.getCode()) {
|
if (0 != response.getCode()) {
|
||||||
model.addAttribute("msg", response.getMsg());
|
model.addAttribute("msg", response.getMsg());
|
||||||
model.addAttribute("fileType",fileAttribute.getSuffix());
|
model.addAttribute("fileType",fileAttribute.getSuffix());
|
||||||
return "fileNotSupported";
|
return "fileNotSupported";
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
File originFile = new File(response.getContent());
|
||||||
|
File previewFile = new File(response.getContent() + ".txt");
|
||||||
|
if (previewFile.exists()) {
|
||||||
|
previewFile.delete();
|
||||||
|
}
|
||||||
|
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());
|
model.addAttribute("ordinaryUrl", response.getMsg());
|
||||||
return "txt";
|
return "txt";
|
||||||
}
|
}
|
||||||
|
|||||||
50
jodconverter-web/src/main/java/cn/keking/utils/CadUtils.java
Normal file
50
jodconverter-web/src/main/java/cn/keking/utils/CadUtils.java
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
package cn.keking.utils;
|
||||||
|
|
||||||
|
import com.aspose.cad.Color;
|
||||||
|
import com.aspose.cad.fileformats.cad.CadDrawTypeMode;
|
||||||
|
import com.aspose.cad.imageoptions.CadRasterizationOptions;
|
||||||
|
import com.aspose.cad.imageoptions.PdfOptions;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author chenjhc
|
||||||
|
* @since 2019/11/21 14:34
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class CadUtils {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(CadUtils.class);
|
||||||
|
|
||||||
|
public boolean cadToPdf(String inputFilePath, String outputFilePath) {
|
||||||
|
com.aspose.cad.Image cadImage = com.aspose.cad.Image.load(inputFilePath);
|
||||||
|
CadRasterizationOptions cadRasterizationOptions = new CadRasterizationOptions();
|
||||||
|
cadRasterizationOptions.setLayouts(new String[]{"Model"});
|
||||||
|
cadRasterizationOptions.setNoScaling(true);
|
||||||
|
cadRasterizationOptions.setBackgroundColor(Color.getWhite());
|
||||||
|
cadRasterizationOptions.setPageWidth(cadImage.getWidth());
|
||||||
|
cadRasterizationOptions.setPageHeight(cadImage.getHeight());
|
||||||
|
cadRasterizationOptions.setPdfProductLocation("center");
|
||||||
|
cadRasterizationOptions.setAutomaticLayoutsScaling(true);
|
||||||
|
cadRasterizationOptions.setDrawType(CadDrawTypeMode.UseObjectColor);
|
||||||
|
PdfOptions pdfOptions = new PdfOptions();
|
||||||
|
pdfOptions.setVectorRasterizationOptions(cadRasterizationOptions);
|
||||||
|
File outputFile = new File(outputFilePath);
|
||||||
|
OutputStream stream;
|
||||||
|
try {
|
||||||
|
stream = new FileOutputStream(outputFile);
|
||||||
|
cadImage.save(stream, pdfOptions);
|
||||||
|
cadImage.close();
|
||||||
|
return true;
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
logger.error("PDFFileNotFoundException,inputFilePath:{}", inputFilePath, e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,18 +2,25 @@ package cn.keking.utils;
|
|||||||
|
|
||||||
import com.sun.star.document.UpdateDocMode;
|
import com.sun.star.document.UpdateDocMode;
|
||||||
import cn.keking.extend.ControlDocumentFormatRegistry;
|
import cn.keking.extend.ControlDocumentFormatRegistry;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.artofsolving.jodconverter.OfficeDocumentConverter;
|
import org.artofsolving.jodconverter.OfficeDocumentConverter;
|
||||||
import org.artofsolving.jodconverter.office.DefaultOfficeManagerConfiguration;
|
import org.artofsolving.jodconverter.office.DefaultOfficeManagerConfiguration;
|
||||||
import org.artofsolving.jodconverter.office.OfficeManager;
|
import org.artofsolving.jodconverter.office.OfficeManager;
|
||||||
import org.artofsolving.jodconverter.office.OfficeUtils;
|
import org.artofsolving.jodconverter.office.OfficeUtils;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.annotation.PreDestroy;
|
import javax.annotation.PreDestroy;
|
||||||
import java.nio.charset.Charset;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建文件转换器
|
* 创建文件转换器
|
||||||
@@ -24,25 +31,35 @@ import java.util.Map;
|
|||||||
@Component
|
@Component
|
||||||
public class ConverterUtils {
|
public class ConverterUtils {
|
||||||
|
|
||||||
// @Value("${office.home}")
|
private final Logger logger = LoggerFactory.getLogger(ConverterUtils.class);
|
||||||
// String officeHome;
|
|
||||||
// OpenOfficeConnection connection;
|
private OfficeManager officeManager;
|
||||||
OfficeManager officeManager;
|
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void initOfficeManager() {
|
public void initOfficeManager() {
|
||||||
//// connection = new SocketOpenOfficeConnection(host,8100);
|
File officeHome;
|
||||||
//// connection.connect();
|
officeHome = OfficeUtils.getDefaultOfficeHome();
|
||||||
String officeHome = OfficeUtils.getDefaultOfficeHome().getAbsolutePath();
|
if (officeHome == null) {
|
||||||
DefaultOfficeManagerConfiguration configuration = new DefaultOfficeManagerConfiguration();
|
throw new RuntimeException("找不到office组件,请确认'office.home'配置是否有误");
|
||||||
configuration.setOfficeHome(officeHome);
|
}
|
||||||
configuration.setPortNumber(8100);
|
boolean killOffice = killProcess();
|
||||||
officeManager = configuration.buildOfficeManager();
|
if (killOffice) {
|
||||||
officeManager.start();
|
logger.warn("检测到有正在运行的office进程,已自动结束该进程");
|
||||||
// 设置任务执行超时为5分钟
|
}
|
||||||
// configuration.setTaskExecutionTimeout(1000 * 60 * 5L);//
|
try {
|
||||||
// 设置任务队列超时为24小时
|
DefaultOfficeManagerConfiguration configuration = new DefaultOfficeManagerConfiguration();
|
||||||
// configuration.setTaskQueueTimeout(1000 * 60 * 60 * 24L);//
|
configuration.setOfficeHome(officeHome);
|
||||||
|
configuration.setPortNumber(8100);
|
||||||
|
// 设置任务执行超时为5分钟
|
||||||
|
configuration.setTaskExecutionTimeout(1000 * 60 * 5L);
|
||||||
|
// 设置任务队列超时为24小时
|
||||||
|
//configuration.setTaskQueueTimeout(1000 * 60 * 60 * 24L);
|
||||||
|
officeManager = configuration.buildOfficeManager();
|
||||||
|
officeManager.start();
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("启动office组件失败,请检查office组件是否可用");
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public OfficeDocumentConverter getDocumentConverter() {
|
public OfficeDocumentConverter getDocumentConverter() {
|
||||||
@@ -56,10 +73,48 @@ public class ConverterUtils {
|
|||||||
loadProperties.put("Hidden", true);
|
loadProperties.put("Hidden", true);
|
||||||
loadProperties.put("ReadOnly", true);
|
loadProperties.put("ReadOnly", true);
|
||||||
loadProperties.put("UpdateDocMode", UpdateDocMode.QUIET_UPDATE);
|
loadProperties.put("UpdateDocMode", UpdateDocMode.QUIET_UPDATE);
|
||||||
loadProperties.put("CharacterSet", Charset.forName("UTF-8").name());
|
loadProperties.put("CharacterSet", StandardCharsets.UTF_8.name());
|
||||||
return loadProperties;
|
return loadProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean killProcess() {
|
||||||
|
boolean flag = false;
|
||||||
|
Properties props = System.getProperties();
|
||||||
|
try {
|
||||||
|
if (props.getProperty("os.name").toLowerCase().contains("windows")) {
|
||||||
|
Process p = Runtime.getRuntime().exec("cmd /c tasklist ");
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
InputStream os = p.getInputStream();
|
||||||
|
byte[] b = new byte[256];
|
||||||
|
while (os.read(b) > 0) {
|
||||||
|
baos.write(b);
|
||||||
|
}
|
||||||
|
String s = baos.toString();
|
||||||
|
if (s.contains("soffice.bin")) {
|
||||||
|
Runtime.getRuntime().exec("taskkill /im " + "soffice.bin" + " /f");
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Process p = Runtime.getRuntime().exec(new String[]{"sh","-c","ps -ef | grep " + "soffice.bin"});
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
InputStream os = p.getInputStream();
|
||||||
|
byte[] b = new byte[256];
|
||||||
|
while (os.read(b) > 0) {
|
||||||
|
baos.write(b);
|
||||||
|
}
|
||||||
|
String s = baos.toString();
|
||||||
|
if (StringUtils.ordinalIndexOf(s, "soffice.bin", 3) > 0) {
|
||||||
|
String[] cmd ={"sh","-c","kill -15 `ps -ef|grep " + "soffice.bin" + "|awk 'NR==1{print $2}'`"};
|
||||||
|
Runtime.getRuntime().exec(cmd);
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error("检测office进程异常", e);
|
||||||
|
}
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
@PreDestroy
|
@PreDestroy
|
||||||
public void destroyOfficeManager(){
|
public void destroyOfficeManager(){
|
||||||
if (null != officeManager && officeManager.isRunning()) {
|
if (null != officeManager && officeManager.isRunning()) {
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
package cn.keking.utils;
|
package cn.keking.utils;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class DeleteFileUtil {
|
public class DeleteFileUtil {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(DeleteFileUtil.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除单个文件
|
* 删除单个文件
|
||||||
*
|
*
|
||||||
@@ -15,14 +22,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,29 +50,30 @@ 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;
|
||||||
// 删除文件夹中的所有文件包括子目录
|
// 删除文件夹中的所有文件包括子目录
|
||||||
File[] files = dirFile.listFiles();
|
File[] files = dirFile.listFiles();
|
||||||
for (int i = 0; i < files.length; i++) {
|
for (int i = 0; i < Objects.requireNonNull(files).length; i++) {
|
||||||
// 删除子文件
|
// 删除子文件
|
||||||
if (files[i].isFile()) {
|
if (files[i].isFile()) {
|
||||||
flag = DeleteFileUtil.deleteFile(files[i].getAbsolutePath());
|
flag = DeleteFileUtil.deleteFile(files[i].getAbsolutePath());
|
||||||
if (!flag)
|
if (!flag) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// 删除子目录
|
} else if (files[i].isDirectory()) {
|
||||||
else if (files[i].isDirectory()) {
|
// 删除子目录
|
||||||
flag = DeleteFileUtil.deleteDirectory(files[i]
|
flag = DeleteFileUtil.deleteDirectory(files[i].getAbsolutePath());
|
||||||
.getAbsolutePath());
|
if (!flag) {
|
||||||
if (!flag)
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
dirFile.delete();
|
||||||
if (!flag) {
|
if (!flag) {
|
||||||
System.out.println("删除目录失败!");
|
LOGGER.info("删除目录失败!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user