mirror of
https://github.com/kekingcn/kkFileView.git
synced 2026-04-01 07:43:10 +00:00
Compare commits
47 Commits
klboke-pat
...
v4.2.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
523623698a | ||
|
|
f714dffe70 | ||
|
|
7a9ad7546c | ||
|
|
138e58a1e1 | ||
|
|
55ca17203f | ||
|
|
8916bee786 | ||
|
|
c055d3d992 | ||
|
|
7b699e08fc | ||
|
|
c7367dfcec | ||
|
|
75a46a14a8 | ||
|
|
181897ec5a | ||
|
|
e5e9611646 | ||
|
|
78d517a16e | ||
|
|
e855c9c7ed | ||
|
|
195f56e9b9 | ||
|
|
888e550453 | ||
|
|
f771d361ae | ||
|
|
2cd23b06f1 | ||
|
|
75e568e15f | ||
|
|
60b91eb79f | ||
|
|
dd7a6465aa | ||
|
|
4cd6a4e4b9 | ||
|
|
3942346f49 | ||
|
|
e697c255fc | ||
|
|
65fa326262 | ||
|
|
81043034f9 | ||
|
|
6c5bceba41 | ||
|
|
b524963892 | ||
|
|
dd4997cedc | ||
|
|
ead5505d53 | ||
|
|
bf6cee4a6a | ||
|
|
bd458bfbe9 | ||
|
|
7895597176 | ||
|
|
a44e5ba518 | ||
|
|
cc7da00001 | ||
|
|
41449aeea6 | ||
|
|
33277bc457 | ||
|
|
f2cfb4cf4a | ||
|
|
d646d72a26 | ||
|
|
1807dbd615 | ||
|
|
1e771ed649 | ||
|
|
83d04ca45d | ||
|
|
ee2dadb40d | ||
|
|
c9eb51213f | ||
|
|
81f28baabf | ||
|
|
1245e9f327 | ||
|
|
007889339b |
@@ -1,5 +1,5 @@
|
||||
FROM keking/kkfileview-jdk:4.1.1
|
||||
MAINTAINER chenjh "842761733@qq.com"
|
||||
ADD server/target/kkFileView-*.tar.gz /opt/
|
||||
ENV KKFILEVIEW_BIN_FOLDER /opt/kkFileView-4.2.0-SNAPSHOT/bin
|
||||
ENTRYPOINT ["java","-Dfile.encoding=UTF-8","-Dspring.config.location=/opt/kkFileView-4.2.0-SNAPSHOT/config/application.properties","-jar","/opt/kkFileView-4.2.0-SNAPSHOT/bin/kkFileView-4.2.0-SNAPSHOT.jar"]
|
||||
ENV KKFILEVIEW_BIN_FOLDER /opt/kkFileView-4.2.0/bin
|
||||
ENTRYPOINT ["java","-Dfile.encoding=UTF-8","-Dspring.config.location=/opt/kkFileView-4.2.0/config/application.properties","-jar","/opt/kkFileView-4.2.0/bin/kkFileView-4.2.0.jar"]
|
||||
|
||||
@@ -47,8 +47,7 @@
|
||||
### 联系我们,加入组织
|
||||
> 我们会用心回答解决大家在项目使用中的问题,也请大家在提问前至少 Google 或 baidu 过,珍爱生命远离无效的交流沟通
|
||||
|
||||

|
||||
|
||||
<img src="./doc/gitee星球.png/" width="60%">
|
||||
|
||||
### 文档预览效果
|
||||
#### 1. 文本预览
|
||||
|
||||
BIN
doc/gitee星球.png
BIN
doc/gitee星球.png
Binary file not shown.
|
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 156 KiB |
4
pom.xml
4
pom.xml
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>cn.keking</groupId>
|
||||
<artifactId>kkFileView-parent</artifactId>
|
||||
<version>4.2.0-SNAPSHOT</version>
|
||||
<version>4.2.0</version>
|
||||
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
@@ -31,7 +31,7 @@
|
||||
<opencv.version>4.1.2-1.5.2</opencv.version>
|
||||
<openblas.version>0.3.6-1.5.1</openblas.version>
|
||||
<ffmpeg.version>4.2.1-1.5.2</ffmpeg.version>
|
||||
<itext.version>2.1.7</itext.version>
|
||||
<itextpdf.version>5.5.13.3</itextpdf.version>
|
||||
<httpclient.version>3.1</httpclient.version>
|
||||
|
||||
<commons-cli.version>1.2</commons-cli.version>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<artifactId>kkFileView-parent</artifactId>
|
||||
<groupId>cn.keking</groupId>
|
||||
<version>4.2.0-SNAPSHOT</version>
|
||||
<version>4.2.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>kkFileView</artifactId>
|
||||
@@ -244,10 +244,10 @@
|
||||
<classifier>windows-x86_64</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lowagie</groupId>
|
||||
<artifactId>itext</artifactId>
|
||||
<version>${itext.version}</version>
|
||||
</dependency>
|
||||
<groupId>com.itextpdf</groupId>
|
||||
<artifactId>itextpdf</artifactId>
|
||||
<version>${itextpdf.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.media</groupId>
|
||||
@@ -338,4 +338,4 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
</project>
|
||||
@@ -7,4 +7,4 @@ echo Please check log file in ../log/kkFileView.log for more information
|
||||
echo You can get help in our official home site: https://kkview.cn
|
||||
echo If you need further help, please join our kk opensource community: https://t.zsxq.com/09ZHSXbsQ
|
||||
echo If this project is helpful to you, please star it on https://gitee.com/kekingcn/file-online-preview/stargazers
|
||||
java -Dspring.config.location=..\config\application.properties -jar kkFileView-4.2.0-SNAPSHOT.jar -> ..\log\kkFileView.log
|
||||
java -Dspring.config.location=..\config\application.properties -jar kkFileView-4.2.0.jar -> ..\log\kkFileView.log
|
||||
|
||||
@@ -51,7 +51,7 @@ else
|
||||
|
||||
## 启动kkFileView
|
||||
echo "Starting kkFileView..."
|
||||
nohup java -Dfile.encoding=UTF-8 -Dspring.config.location=../config/application.properties -jar kkFileView-4.2.0-SNAPSHOT.jar > ../log/kkFileView.log 2>&1 &
|
||||
nohup java -Dfile.encoding=UTF-8 -Dspring.config.location=../config/application.properties -jar kkFileView-4.2.0.jar > ../log/kkFileView.log 2>&1 &
|
||||
echo "Please execute ./showlog.sh to check log for more information"
|
||||
echo "You can get help in our official home site: https://kkview.cn"
|
||||
echo "If you need further help, please join our kk opensource community: https://t.zsxq.com/09ZHSXbsQ"
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
server.port = ${KK_SERVER_PORT:8012}
|
||||
server.servlet.context-path= ${KK_CONTEXT_PATH:/}
|
||||
server.servlet.encoding.charset = utf-8
|
||||
#文件上传限制
|
||||
#文件上传限制前端
|
||||
spring.servlet.multipart.max-file-size=500MB
|
||||
#文件上传限制
|
||||
spring.servlet.multipart.max-request-size=500MB
|
||||
## Freemarker 配置
|
||||
spring.freemarker.template-loader-path = classpath:/web/
|
||||
@@ -117,3 +118,9 @@ watermark.angle = ${WATERMARK_ANGLE:10}
|
||||
#Tif类型图片浏览模式:tif(利用前端js插件浏览);jpg(转换为jpg后前端显示);pdf(转换为pdf后显示,便于打印)
|
||||
tif.preview.type = ${KK_TIF_PREVIEW_TYPE:tif}
|
||||
|
||||
# 备案信息
|
||||
BeiAn =
|
||||
#禁止上传类型
|
||||
prohibit =exe,dll,dat
|
||||
#删除密码
|
||||
sc.password =123456
|
||||
|
||||
@@ -42,6 +42,10 @@ public class ConfigConstants {
|
||||
private static String pdfBookmarkDisable;
|
||||
private static Boolean fileUploadDisable;
|
||||
private static String tifPreviewType;
|
||||
private static String BeiAn;
|
||||
private static String[] prohibit= {};
|
||||
private static String size;
|
||||
private static String password;
|
||||
|
||||
public static final String DEFAULT_CACHE_ENABLED = "true";
|
||||
public static final String DEFAULT_TXT_TYPE = "txt,html,htm,asp,jsp,xml,json,properties,md,gitignore,log,java,py,c,cpp,sql,sh,bat,m,bas,prg,cmd";
|
||||
@@ -62,6 +66,10 @@ public class ConfigConstants {
|
||||
public static final String DEFAULT_PDF_BOOKMARK_DISABLE = "true";
|
||||
public static final String DEFAULT_FILE_UPLOAD_DISABLE = "false";
|
||||
public static final String DEFAULT_TIF_PREVIEW_TYPE = "tif";
|
||||
public static final String DEFAULT_BeiAn_DISABLE = "无";
|
||||
public static final String DEFAULT_size_DISABLE = "500MB";
|
||||
public static final String DEFAULT_prohibit_DISABLE = "exe,dll";
|
||||
public static final String DEFAULT_password_DISABLE = "123456";
|
||||
|
||||
public static Boolean isCacheEnabled() {
|
||||
return cacheEnabled;
|
||||
@@ -353,4 +361,49 @@ public class ConfigConstants {
|
||||
public static void setTifPreviewTypeValue(String tifPreviewType) {
|
||||
ConfigConstants.tifPreviewType = tifPreviewType;
|
||||
}
|
||||
|
||||
public static String getBeiAn() {
|
||||
return BeiAn;
|
||||
}
|
||||
@Value("${BeiAn:无}")
|
||||
public void setBeiAn(String BeiAn) {
|
||||
setBeiAnValue(BeiAn);
|
||||
}
|
||||
public static void setBeiAnValue(String BeiAn) {
|
||||
ConfigConstants.BeiAn = BeiAn;
|
||||
}
|
||||
public static String[] getprohibit() {
|
||||
return prohibit;
|
||||
}
|
||||
@Value("${prohibit:exe,dll}")
|
||||
public void setprohibit(String prohibit) {
|
||||
String[] prohibittArr = prohibit.split(",");
|
||||
setprohibitValue(prohibittArr);
|
||||
}
|
||||
|
||||
public static void setprohibitValue(String[] prohibit) {
|
||||
ConfigConstants.prohibit = prohibit;
|
||||
}
|
||||
public static String maxsize() {
|
||||
return size;
|
||||
}
|
||||
@Value("${spring.servlet.multipart.max-file-size:500MB}")
|
||||
public void setsize(String size) {
|
||||
setsizeValue(size);
|
||||
}
|
||||
public static void setsizeValue(String size) {
|
||||
ConfigConstants.size = size;
|
||||
}
|
||||
|
||||
public static String getpassword() {
|
||||
return password;
|
||||
}
|
||||
@Value("${sc.password:123456}")
|
||||
public void setpassword(String password) {
|
||||
setpasswordValue(password);
|
||||
}
|
||||
public static void setpasswordValue(String password) {
|
||||
ConfigConstants.password = password;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -53,7 +53,11 @@ public class ConfigRefreshComponent {
|
||||
String pdfBookmarkDisable;
|
||||
boolean fileUploadDisable;
|
||||
String tifPreviewType;
|
||||
|
||||
String prohibit;
|
||||
String[] prohibitArray;
|
||||
String BeiAn;
|
||||
String size;
|
||||
String password;
|
||||
while (true) {
|
||||
FileReader fileReader = new FileReader(configFilePath);
|
||||
BufferedReader bufferedReader = new BufferedReader(fileReader);
|
||||
@@ -78,6 +82,11 @@ public class ConfigRefreshComponent {
|
||||
pdfBookmarkDisable = properties.getProperty("pdf.bookmark.disable", ConfigConstants.DEFAULT_PDF_BOOKMARK_DISABLE);
|
||||
fileUploadDisable = Boolean.parseBoolean(properties.getProperty("file.upload.disable", ConfigConstants.DEFAULT_FILE_UPLOAD_DISABLE));
|
||||
tifPreviewType = properties.getProperty("tif.preview.type", ConfigConstants.DEFAULT_TIF_PREVIEW_TYPE);
|
||||
size = properties.getProperty("spring.servlet.multipart.max-file-size", ConfigConstants.DEFAULT_size_DISABLE);
|
||||
BeiAn = properties.getProperty("BeiAn", ConfigConstants.DEFAULT_BeiAn_DISABLE);
|
||||
prohibit = properties.getProperty("prohibit", ConfigConstants.DEFAULT_prohibit_DISABLE);
|
||||
password = properties.getProperty("sc.password", ConfigConstants.DEFAULT_password_DISABLE);
|
||||
prohibitArray = prohibit.split(",");
|
||||
|
||||
ConfigConstants.setCacheEnabledValueValue(cacheEnabled);
|
||||
ConfigConstants.setSimTextValue(textArray);
|
||||
@@ -96,6 +105,10 @@ public class ConfigRefreshComponent {
|
||||
ConfigConstants.setPdfBookmarkDisableValue(pdfBookmarkDisable);
|
||||
ConfigConstants.setFileUploadDisableValue(fileUploadDisable);
|
||||
ConfigConstants.setTifPreviewTypeValue(tifPreviewType);
|
||||
ConfigConstants.setBeiAnValue(BeiAn);
|
||||
ConfigConstants.setsizeValue(size);
|
||||
ConfigConstants.setprohibitValue(prohibitArray);
|
||||
ConfigConstants.setpasswordValue(password);
|
||||
setWatermarkConfig(properties);
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
|
||||
@@ -2,31 +2,22 @@ package cn.keking.service;
|
||||
|
||||
import cn.keking.config.ConfigConstants;
|
||||
import cn.keking.model.FileType;
|
||||
import cn.keking.utils.FileHeaderRar;
|
||||
import cn.keking.utils.KkFileUtils;
|
||||
import cn.keking.utils.RarUtils;
|
||||
import cn.keking.web.filter.BaseUrlFilter;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.github.junrar.Archive;
|
||||
import com.github.junrar.exception.RarException;
|
||||
import com.github.junrar.rarfile.FileHeader;
|
||||
import net.sf.sevenzipjbinding.*;
|
||||
import net.sf.sevenzipjbinding.ExtractOperationResult;
|
||||
import net.sf.sevenzipjbinding.IInArchive;
|
||||
import net.sf.sevenzipjbinding.SevenZip;
|
||||
import net.sf.sevenzipjbinding.SevenZipException;
|
||||
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
|
||||
import net.sf.sevenzipjbinding.simple.ISimpleInArchive;
|
||||
import net.sf.sevenzipjbinding.simple.ISimpleInArchiveItem;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.*;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.CollationKey;
|
||||
import java.text.Collator;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yudian-it
|
||||
@@ -34,171 +25,61 @@ import java.util.stream.Collectors;
|
||||
*/
|
||||
@Component
|
||||
public class CompressFileReader {
|
||||
|
||||
private static final Pattern pattern = Pattern.compile("^\\d+");
|
||||
private final FileHandlerService fileHandlerService;
|
||||
private final String fileDir = ConfigConstants.getFileDir();
|
||||
private final ExecutorService executors = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
|
||||
|
||||
public CompressFileReader(FileHandlerService fileHandlerService) {
|
||||
this.fileHandlerService = fileHandlerService;
|
||||
}
|
||||
|
||||
public static byte[] getUTF8BytesFromGBKString(String gbkStr) {
|
||||
int n = gbkStr.length();
|
||||
byte[] utfBytes = new byte[3 * n];
|
||||
int k = 0;
|
||||
for (int i = 0; i < n; i++) {
|
||||
int m = gbkStr.charAt(i);
|
||||
if (m < 128 && m >= 0) {
|
||||
utfBytes[k++] = (byte) m;
|
||||
continue;
|
||||
}
|
||||
utfBytes[k++] = (byte) (0xe0 | (m >> 12));
|
||||
utfBytes[k++] = (byte) (0x80 | ((m >> 6) & 0x3f));
|
||||
utfBytes[k++] = (byte) (0x80 | (m & 0x3f));
|
||||
}
|
||||
if (k < utfBytes.length) {
|
||||
byte[] tmp = new byte[k];
|
||||
System.arraycopy(utfBytes, 0, tmp, 0, k);
|
||||
return tmp;
|
||||
}
|
||||
return utfBytes;
|
||||
}
|
||||
|
||||
public String getUtf8String(String str) {
|
||||
if (str != null && str.length() > 0) {
|
||||
String needEncodeCode = "ISO-8859-1";
|
||||
String neeEncodeCode = "ISO-8859-2";
|
||||
String gbkEncodeCode = "GBK";
|
||||
try {
|
||||
if (Charset.forName(needEncodeCode).newEncoder().canEncode(str)) {
|
||||
str = new String(str.getBytes(needEncodeCode), StandardCharsets.UTF_8);
|
||||
}
|
||||
if (Charset.forName(neeEncodeCode).newEncoder().canEncode(str)) {
|
||||
str = new String(str.getBytes(neeEncodeCode), StandardCharsets.UTF_8);
|
||||
}
|
||||
if (Charset.forName(gbkEncodeCode).newEncoder().canEncode(str)) {
|
||||
str = new String(getUTF8BytesFromGBKString(str), StandardCharsets.UTF_8);
|
||||
}
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
/**
|
||||
* 判断是否是中日韩文字
|
||||
*/
|
||||
private static boolean isChinese(char c) {
|
||||
Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
|
||||
if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
|
||||
|| ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
|
||||
|| ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
|
||||
|| ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
|
||||
|| ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
|
||||
|| ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static boolean judge(char c){
|
||||
if((c >='0' && c<='9')||(c >='a' && c<='z' || c >='A' && c<='Z')){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static boolean isMessyCode(String strName) {
|
||||
//去除字符串中的空格 制表符 换行 回车
|
||||
Pattern p = Pattern.compile("\\s*|\t*|\r*|\n*");
|
||||
Matcher m = p.matcher(strName);
|
||||
String after = m.replaceAll("").replaceAll("\\+", "").replaceAll("#", "").replaceAll("&", "");
|
||||
//去除字符串中的标点符号
|
||||
String temp = after.replaceAll("\\p{P}", "");
|
||||
//处理之后转换成字符数组
|
||||
char[] ch = temp.trim().toCharArray();
|
||||
for (int i = 0; i < ch.length; i++) {
|
||||
char c = ch[i];
|
||||
//判断是否是数字或者英文字符
|
||||
if (!judge(c)) {
|
||||
//判断是否是中日韩文
|
||||
if (!isChinese(c)) {
|
||||
//如果不是数字或者英文字符也不是中日韩文则表示是乱码返回true
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
//表示不是乱码 返回false
|
||||
return false;
|
||||
}
|
||||
|
||||
public String unRar(String filePath, String fileKey) {
|
||||
Map<String, FileNode> appender = new HashMap<>();
|
||||
public String unRar(String paths, String passWord, String fileName) throws Exception {
|
||||
List<String> imgUrls = new ArrayList<>();
|
||||
String baseUrl = BaseUrlFilter.getBaseUrl();
|
||||
try {
|
||||
List<FileHeaderRar> items = getRar4Paths(filePath);
|
||||
String archiveFileName = fileHandlerService.getFileNameFromPath(filePath);
|
||||
List<Map<String, FileHeaderRar>> headersToBeExtract = new ArrayList<>();
|
||||
for (FileHeaderRar header : items) {
|
||||
String fullName = header.getFileNameW();
|
||||
String originName = getLastFileName(fullName);
|
||||
String childName = originName;
|
||||
boolean directory = header.getDirectory();
|
||||
if (!directory) {
|
||||
childName = archiveFileName + "_" + originName;
|
||||
headersToBeExtract.add(Collections.singletonMap(childName, header));
|
||||
}
|
||||
String parentName = getLast2FileName(fullName, archiveFileName);
|
||||
FileType type = FileType.typeFromUrl(childName);
|
||||
if (type.equals(FileType.PICTURE)) {
|
||||
imgUrls.add(baseUrl + childName);
|
||||
}
|
||||
FileNode node =
|
||||
new FileNode(originName, childName, parentName, new ArrayList<>(), directory, fileKey);
|
||||
addNodes(appender, parentName, node);
|
||||
appender.put(childName, node);
|
||||
}
|
||||
fileHandlerService.putImgCache(fileKey, imgUrls);
|
||||
executors.submit(new RarExtractorWorker(headersToBeExtract, filePath));
|
||||
return new ObjectMapper().writeValueAsString(appender.get(""));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<FileHeaderRar> getRar4Paths(String paths) {
|
||||
String archiveFileName = fileHandlerService.getFileNameFromPath(paths);
|
||||
RandomAccessFile randomAccessFile = null;
|
||||
IInArchive inArchive = null;
|
||||
List<FileHeaderRar> itemPath = null;
|
||||
try {
|
||||
randomAccessFile = new RandomAccessFile(paths, "r");
|
||||
inArchive = SevenZip.openInArchive(null, new RandomAccessFileInStream(randomAccessFile));
|
||||
String folderName = paths.substring(paths.lastIndexOf(File.separator) + 1);
|
||||
String extractPath = paths.substring(0, paths.lastIndexOf(folderName));
|
||||
inArchive.extract(null, false, new ExtractCallback(inArchive, extractPath, folderName + "_"));
|
||||
ISimpleInArchive simpleInArchive = inArchive.getSimpleInterface();
|
||||
itemPath = Arrays.stream(simpleInArchive.getArchiveItems()).map(o -> {
|
||||
try {
|
||||
String path = getUtf8String(o.getPath());
|
||||
if (isMessyCode(path)){
|
||||
path = new String(o.getPath().getBytes(StandardCharsets.ISO_8859_1), "GBK");
|
||||
}
|
||||
return new FileHeaderRar(path, o.isFolder());
|
||||
} catch (SevenZipException e) {
|
||||
e.printStackTrace();
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.collect(Collectors.toList())
|
||||
.stream()
|
||||
.sorted(Comparator.comparing(FileHeaderRar::getFileNameW))
|
||||
.collect(Collectors.toList());
|
||||
ISimpleInArchive simpleInArchive = inArchive.getSimpleInterface();
|
||||
final String[] str = {null};
|
||||
for (final ISimpleInArchiveItem item : simpleInArchive.getArchiveItems()) {
|
||||
if (!item.isFolder()) {
|
||||
ExtractOperationResult result;
|
||||
result = item.extractSlow(data -> {
|
||||
try {
|
||||
str[0] = RarUtils.getUtf8String(item.getPath());
|
||||
if (RarUtils.isMessyCode(str[0])){
|
||||
str[0] = new String(item.getPath().getBytes(StandardCharsets.ISO_8859_1), "gbk");
|
||||
}
|
||||
str[0] = str[0].replace("\\", File.separator); //Linux 下路径错误
|
||||
String str1 = str[0].substring(0, str[0].lastIndexOf(File.separator)+ 1);
|
||||
File file = new File(extractPath, folderName + "_" + File.separator + str1);
|
||||
if (!file.exists()) {
|
||||
file.mkdirs();
|
||||
}
|
||||
OutputStream out = new FileOutputStream( extractPath+ folderName + "_" + File.separator + str[0], true);
|
||||
IOUtils.write(data, out);
|
||||
out.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return data.length;
|
||||
}, passWord);
|
||||
if (result == ExtractOperationResult.OK) {
|
||||
FileType type = FileType.typeFromUrl(str[0]);
|
||||
if (type.equals(FileType.PICTURE)) {
|
||||
// System.out.println( baseUrl +folderName + "_" + str[0]);
|
||||
imgUrls.add(baseUrl +folderName + "_/" + str[0].replace("\\", "/"));
|
||||
}
|
||||
fileHandlerService.putImgCache(fileName, imgUrls);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return archiveFileName + "_";
|
||||
} catch (Exception e) {
|
||||
System.err.println("Error occurs: " + e);
|
||||
throw new Exception(e);
|
||||
} finally {
|
||||
if (inArchive != null) {
|
||||
try {
|
||||
@@ -215,276 +96,6 @@ public class CompressFileReader {
|
||||
}
|
||||
}
|
||||
}
|
||||
return itemPath;
|
||||
}
|
||||
|
||||
private void addNodes(Map<String, FileNode> appender, String parentName, FileNode node) {
|
||||
if (appender.containsKey(parentName)) {
|
||||
appender.get(parentName).getChildList().add(node);
|
||||
appender.get(parentName).getChildList().sort(sortComparator);
|
||||
} else {
|
||||
// 根节点
|
||||
FileNode nodeRoot = new FileNode(parentName, parentName, "", new ArrayList<>(), true);
|
||||
nodeRoot.getChildList().add(node);
|
||||
appender.put("", nodeRoot);
|
||||
appender.put(parentName, nodeRoot);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getLast2FileName(String fullName, String rootName) {
|
||||
if (fullName.endsWith(File.separator)) {
|
||||
fullName = fullName.substring(0, fullName.length() - 1);
|
||||
}
|
||||
// 1.获取剩余部分
|
||||
int endIndex = fullName.lastIndexOf(File.separator);
|
||||
String leftPath = fullName.substring(0, endIndex == -1 ? 0 : endIndex);
|
||||
if (leftPath.length() > 1) {
|
||||
// 2.获取倒数第二个
|
||||
return getLastFileName(leftPath);
|
||||
} else {
|
||||
return rootName;
|
||||
}
|
||||
}
|
||||
|
||||
private static String getLastFileName(String fullName) {
|
||||
if (fullName.endsWith(File.separator)) {
|
||||
fullName = fullName.substring(0, fullName.length() - 1);
|
||||
}
|
||||
String newName = fullName;
|
||||
if (fullName.contains(File.separator)) {
|
||||
newName = fullName.substring(fullName.lastIndexOf(File.separator) + 1);
|
||||
}
|
||||
return newName;
|
||||
}
|
||||
|
||||
public static Comparator<FileNode> sortComparator = new Comparator<FileNode>() {
|
||||
final Collator cmp = Collator.getInstance(Locale.US);
|
||||
|
||||
@Override
|
||||
public int compare(FileNode o1, FileNode o2) {
|
||||
// 判断两个对比对象是否是开头包含数字,如果包含数字则获取数字并按数字真正大小进行排序
|
||||
BigDecimal num1, num2;
|
||||
if (null != (num1 = isStartNumber(o1))
|
||||
&& null != (num2 = isStartNumber(o2))) {
|
||||
return num1.subtract(num2).intValue();
|
||||
}
|
||||
CollationKey c1 = cmp.getCollationKey(o1.getOriginName());
|
||||
CollationKey c2 = cmp.getCollationKey(o2.getOriginName());
|
||||
return cmp.compare(c1.getSourceString(), c2.getSourceString());
|
||||
}
|
||||
};
|
||||
|
||||
private static BigDecimal isStartNumber(FileNode src) {
|
||||
Matcher matcher = pattern.matcher(src.getOriginName());
|
||||
if (matcher.find()) {
|
||||
return new BigDecimal(matcher.group());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static class FileNode {
|
||||
|
||||
private String originName;
|
||||
private String fileName;
|
||||
private String parentFileName;
|
||||
private boolean directory;
|
||||
//用于图片预览时寻址
|
||||
private String fileKey;
|
||||
private List<FileNode> childList;
|
||||
|
||||
public FileNode(String originName, String fileName, String parentFileName, List<FileNode> childList, boolean directory) {
|
||||
this.originName = originName;
|
||||
this.fileName = fileName;
|
||||
this.parentFileName = parentFileName;
|
||||
this.childList = childList;
|
||||
this.directory = directory;
|
||||
}
|
||||
|
||||
public FileNode(String originName, String fileName, String parentFileName, List<FileNode> childList, boolean directory, String fileKey) {
|
||||
this.originName = originName;
|
||||
this.fileName = fileName;
|
||||
this.parentFileName = parentFileName;
|
||||
this.childList = childList;
|
||||
this.directory = directory;
|
||||
this.fileKey = fileKey;
|
||||
}
|
||||
|
||||
public String getFileKey() {
|
||||
return fileKey;
|
||||
}
|
||||
|
||||
public void setFileKey(String fileKey) {
|
||||
this.fileKey = fileKey;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public void setFileName(String fileName) {
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public String getParentFileName() {
|
||||
return parentFileName;
|
||||
}
|
||||
|
||||
public void setParentFileName(String parentFileName) {
|
||||
this.parentFileName = parentFileName;
|
||||
}
|
||||
|
||||
public List<FileNode> getChildList() {
|
||||
return childList;
|
||||
}
|
||||
|
||||
public void setChildList(List<FileNode> childList) {
|
||||
this.childList = childList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
try {
|
||||
return new ObjectMapper().writeValueAsString(this);
|
||||
} catch (JsonProcessingException e) {
|
||||
e.printStackTrace();
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public String getOriginName() {
|
||||
return originName;
|
||||
}
|
||||
|
||||
public void setOriginName(String originName) {
|
||||
this.originName = originName;
|
||||
}
|
||||
|
||||
public boolean isDirectory() {
|
||||
return directory;
|
||||
}
|
||||
|
||||
public void setDirectory(boolean directory) {
|
||||
this.directory = directory;
|
||||
}
|
||||
}
|
||||
|
||||
class RarExtractorWorker implements Runnable {
|
||||
private final List<Map<String, FileHeader>> headersToBeExtracted;
|
||||
|
||||
private final List<Map<String, FileHeaderRar>> headersToBeExtract;
|
||||
|
||||
private final Archive archive;
|
||||
/**
|
||||
* 用以删除源文件
|
||||
*/
|
||||
private final String filePath;
|
||||
|
||||
public RarExtractorWorker(
|
||||
List<Map<String, FileHeader>> headersToBeExtracted, Archive archive, String filePath) {
|
||||
this.headersToBeExtracted = headersToBeExtracted;
|
||||
this.archive = archive;
|
||||
this.filePath = filePath;
|
||||
headersToBeExtract = null;
|
||||
}
|
||||
|
||||
public RarExtractorWorker(
|
||||
List<Map<String, FileHeaderRar>> headersToBeExtract, String filePath) {
|
||||
this.headersToBeExtract = headersToBeExtract;
|
||||
this.filePath = filePath;
|
||||
archive = null;
|
||||
headersToBeExtracted = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (Map<String, FileHeader> entryMap : headersToBeExtracted) {
|
||||
String childName = entryMap.keySet().iterator().next();
|
||||
extractRarFile(childName, entryMap.values().iterator().next(), archive);
|
||||
}
|
||||
try {
|
||||
archive.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
KkFileUtils.deleteFileByPath(filePath);
|
||||
}
|
||||
|
||||
private void extractRarFile(String childName, FileHeader header, Archive archive) {
|
||||
String outPath = fileDir + childName;
|
||||
try (OutputStream ot = new FileOutputStream(outPath)) {
|
||||
archive.extractFile(header, ot);
|
||||
} catch (IOException | RarException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class ExtractCallback implements IArchiveExtractCallback {
|
||||
private final IInArchive inArchive;
|
||||
|
||||
private final String extractPath;
|
||||
private final String folderName;
|
||||
|
||||
public ExtractCallback(IInArchive inArchive, String extractPath, String folderName) {
|
||||
this.inArchive = inArchive;
|
||||
if (!extractPath.endsWith("/") && !extractPath.endsWith("\\")) {
|
||||
extractPath += File.separator;
|
||||
}
|
||||
this.extractPath = extractPath;
|
||||
this.folderName = folderName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTotal(long total) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCompleted(long complete) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ISequentialOutStream getStream(int index, ExtractAskMode extractAskMode) throws SevenZipException {
|
||||
String filePath = inArchive.getStringProperty(index, PropID.PATH);
|
||||
String real = folderName + filePath.substring(filePath.lastIndexOf(File.separator) + 1);
|
||||
File f = new File(extractPath + real);
|
||||
f.delete();
|
||||
return data -> {
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
File path = new File(extractPath + real);
|
||||
if (!path.getParentFile().exists()) {
|
||||
path.getParentFile().mkdirs();
|
||||
}
|
||||
if (!path.exists()) {
|
||||
path.createNewFile();
|
||||
}
|
||||
fos = new FileOutputStream(path, true);
|
||||
fos.write(data);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
if (fos != null) {
|
||||
fos.flush();
|
||||
fos.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return data.length;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareOperation(ExtractAskMode extractAskMode) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOperationResult(ExtractOperationResult extractOperationResult) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ import org.springframework.util.StringUtils;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
@@ -273,6 +275,14 @@ public class FileHandlerService {
|
||||
FileType type;
|
||||
String fileName;
|
||||
String fullFileName = WebUtils.getUrlParameterReg(url, "fullfilename");
|
||||
String urlStrr = null;
|
||||
URL urll;
|
||||
try {
|
||||
urll = new URL(url);
|
||||
urlStrr = URLDecoder.decode(urll.getPath(), "UTF-8");
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
if (StringUtils.hasText(fullFileName)) {
|
||||
fileName = fullFileName;
|
||||
type = FileType.typeFromFileName(fullFileName);
|
||||
@@ -283,8 +293,10 @@ public class FileHandlerService {
|
||||
suffix = WebUtils.suffixFromUrl(url);
|
||||
}
|
||||
if (url.contains("?fileKey=")) {
|
||||
fileName=urlStrr;
|
||||
attribute.setSkipDownLoad(true);
|
||||
}
|
||||
// System.out.println(fileName);
|
||||
url = WebUtils.encodeUrlFileName(url);
|
||||
fileName = KkFileUtils.htmlEscape(fileName); //文件名处理
|
||||
attribute.setType(type);
|
||||
|
||||
20
server/src/main/java/cn/keking/service/ZtreeNodeVo.java
Normal file
20
server/src/main/java/cn/keking/service/ZtreeNodeVo.java
Normal file
@@ -0,0 +1,20 @@
|
||||
package cn.keking.service;
|
||||
import java.util.List;
|
||||
public class ZtreeNodeVo {
|
||||
public String id;
|
||||
public String pid;
|
||||
public String name;
|
||||
public List<ZtreeNodeVo> children;
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public void setPid(String pid) {
|
||||
this.pid = pid;
|
||||
}
|
||||
public void setChildren(List<ZtreeNodeVo> children) {
|
||||
this.children = children;
|
||||
}
|
||||
}
|
||||
@@ -7,10 +7,15 @@ import cn.keking.service.FilePreview;
|
||||
import cn.keking.utils.DownloadUtils;
|
||||
import cn.keking.service.FileHandlerService;
|
||||
import cn.keking.service.CompressFileReader;
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
import org.apache.poi.EncryptedDocumentException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Created by kl on 2018/1/17.
|
||||
* Content :处理压缩包文件
|
||||
@@ -21,7 +26,7 @@ public class CompressFilePreviewImpl implements FilePreview {
|
||||
private final FileHandlerService fileHandlerService;
|
||||
private final CompressFileReader compressFileReader;
|
||||
private final OtherFilePreviewImpl otherFilePreview;
|
||||
|
||||
private static final String Rar_PASSWORD_MSG = "password";
|
||||
public CompressFilePreviewImpl(FileHandlerService fileHandlerService, CompressFileReader compressFileReader, OtherFilePreviewImpl otherFilePreview) {
|
||||
this.fileHandlerService = fileHandlerService;
|
||||
this.compressFileReader = compressFileReader;
|
||||
@@ -31,7 +36,8 @@ public class CompressFilePreviewImpl implements FilePreview {
|
||||
@Override
|
||||
public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
|
||||
String fileName=fileAttribute.getName();
|
||||
String fileTree;
|
||||
String filePassword = fileAttribute.getFilePassword();
|
||||
String fileTree = null;
|
||||
// 判断文件名是否存在(redis缓存读取)
|
||||
if (!StringUtils.hasText(fileHandlerService.getConvertedFile(fileName)) || !ConfigConstants.isCacheEnabled()) {
|
||||
ReturnResponse<String> response = DownloadUtils.downLoad(fileAttribute, fileName);
|
||||
@@ -39,21 +45,32 @@ public class CompressFilePreviewImpl implements FilePreview {
|
||||
return otherFilePreview.notSupportedFile(model, fileAttribute, response.getMsg());
|
||||
}
|
||||
String filePath = response.getContent();
|
||||
fileTree = compressFileReader.unRar(filePath, fileName);
|
||||
if (fileTree != null && !"null".equals(fileTree)) {
|
||||
try {
|
||||
fileTree = compressFileReader.unRar(filePath, filePassword,fileName);
|
||||
} catch (Exception e) {
|
||||
Throwable[] throwableArray = ExceptionUtils.getThrowables(e);
|
||||
for (Throwable throwable : throwableArray) {
|
||||
if (throwable instanceof IOException || throwable instanceof EncryptedDocumentException) {
|
||||
if (e.getMessage().toLowerCase().contains(Rar_PASSWORD_MSG)) {
|
||||
model.addAttribute("needFilePassword", true);
|
||||
return EXEL_FILE_PREVIEW_PAGE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ObjectUtils.isEmpty(fileTree)) {
|
||||
if (ConfigConstants.isCacheEnabled()) {
|
||||
// 加入缓存
|
||||
fileHandlerService.addConvertedFile(fileName, fileTree);
|
||||
}
|
||||
}else {
|
||||
return otherFilePreview.notSupportedFile(model, fileAttribute, "压缩文件密码错误! 压缩文件损坏! 压缩文件类型不受支持!");
|
||||
}
|
||||
} else {
|
||||
fileTree = fileHandlerService.getConvertedFile(fileName);
|
||||
}
|
||||
if (fileTree != null && !"null".equals(fileTree)) {
|
||||
model.addAttribute("fileName", fileName);
|
||||
model.addAttribute("fileTree", fileTree);
|
||||
return COMPRESS_FILE_PREVIEW_PAGE;
|
||||
} else {
|
||||
return otherFilePreview.notSupportedFile(model, fileAttribute, "压缩文件类型不受支持");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,13 +3,11 @@ package cn.keking.service.impl;
|
||||
import cn.keking.config.ConfigConstants;
|
||||
import cn.keking.model.FileAttribute;
|
||||
import cn.keking.model.ReturnResponse;
|
||||
import cn.keking.service.FileHandlerService;
|
||||
import cn.keking.service.FilePreview;
|
||||
import cn.keking.utils.ConvertPicUtil;
|
||||
import cn.keking.utils.DownloadUtils;
|
||||
import cn.keking.utils.WebUtils;
|
||||
import cn.keking.web.filter.BaseUrlFilter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -27,72 +25,64 @@ import java.util.List;
|
||||
@Service
|
||||
public class TiffFilePreviewImpl implements FilePreview {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(TiffFilePreviewImpl.class);
|
||||
|
||||
private final PictureFilePreviewImpl pictureFilePreview;
|
||||
private static final String INITIALIZE_MEMORY_SIZE = "initializeMemorySize";
|
||||
//默认初始化 50MB 内存
|
||||
private static final long INITIALIZE_MEMORY_SIZE_VALUE_DEFAULT = 1024L * 1024 * 50;
|
||||
|
||||
private final String fileDir = ConfigConstants.getFileDir();
|
||||
|
||||
public TiffFilePreviewImpl(PictureFilePreviewImpl pictureFilePreview) {
|
||||
this.pictureFilePreview = pictureFilePreview;
|
||||
private final FileHandlerService fileHandlerService;
|
||||
private final OtherFilePreviewImpl otherFilePreview;
|
||||
public TiffFilePreviewImpl(FileHandlerService fileHandlerService,OtherFilePreviewImpl otherFilePreview) {
|
||||
this.fileHandlerService = fileHandlerService;
|
||||
this.otherFilePreview = otherFilePreview;
|
||||
}
|
||||
|
||||
private final String fileDir = ConfigConstants.getFileDir();
|
||||
@Override
|
||||
public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
|
||||
String fileName = fileAttribute.getName();
|
||||
String baseUrl = BaseUrlFilter.getBaseUrl();
|
||||
String tifPreviewType = ConfigConstants.getTifPreviewType();
|
||||
String tifOnLinePreviewType = fileAttribute.getTifPreviewType();
|
||||
if (StringUtils.hasText(tifOnLinePreviewType)) {
|
||||
tifPreviewType = tifOnLinePreviewType;
|
||||
}
|
||||
|
||||
if ("tif".equalsIgnoreCase(tifPreviewType)) {
|
||||
|
||||
pictureFilePreview.filePreviewHandle(url, model, fileAttribute);
|
||||
String fileSize = WebUtils.getUrlParameterReg(url, INITIALIZE_MEMORY_SIZE);
|
||||
if (StringUtils.hasText(fileSize)) {
|
||||
model.addAttribute(INITIALIZE_MEMORY_SIZE, fileSize);
|
||||
} else {
|
||||
model.addAttribute(INITIALIZE_MEMORY_SIZE, Long.toString(INITIALIZE_MEMORY_SIZE_VALUE_DEFAULT));
|
||||
}
|
||||
model.addAttribute("currentUrl", url);
|
||||
return TIFF_FILE_PREVIEW_PAGE;
|
||||
|
||||
} else if ("jpg".equalsIgnoreCase(tifPreviewType) || "pdf".equalsIgnoreCase(tifPreviewType)) {
|
||||
String inputFileName = url.substring(url.lastIndexOf("/") + 1);
|
||||
String inputFileNamePrefix = inputFileName.substring(0, inputFileName.lastIndexOf("."));
|
||||
|
||||
String strLocalTif = fileDir + inputFileName;
|
||||
File fileTiff = new File(strLocalTif);
|
||||
// 如果本地不存在这个tif文件,则下载
|
||||
if (!fileTiff.exists()) {
|
||||
ReturnResponse<String> response = DownloadUtils.downLoad(fileAttribute, inputFileName);
|
||||
if (response.isFailure()) {
|
||||
return NOT_SUPPORTED_FILE_PAGE;
|
||||
}
|
||||
}
|
||||
|
||||
String baseUrl = BaseUrlFilter.getBaseUrl();
|
||||
String pdfName = fileName.substring(0, fileName.lastIndexOf(".") + 1) + "pdf";
|
||||
String jpgName = fileName.substring(0, fileName.lastIndexOf(".") + 1) + "jpg";
|
||||
String strLocalTif = fileDir + fileName;
|
||||
String outFilePath = fileDir + pdfName;
|
||||
if ("pdf".equalsIgnoreCase(tifPreviewType)) {
|
||||
// 以PDF模式预览的过程
|
||||
File filePdf = new File(fileDir + inputFileNamePrefix + ".pdf");
|
||||
// 如果本地不存在对应的pdf,则调用转换过程。否则直接用现有的pdf文件
|
||||
if (!filePdf.exists()) {
|
||||
filePdf = ConvertPicUtil.convertTif2Pdf(strLocalTif, fileDir + inputFileNamePrefix + ".pdf");
|
||||
}
|
||||
|
||||
// 如果pdf已经存在,则将url路径加入到对象中,返回给页面
|
||||
assert filePdf != null;
|
||||
if (filePdf.exists()) {
|
||||
String pdfUrl = baseUrl + inputFileNamePrefix + ".pdf";
|
||||
model.addAttribute("pdfUrl", pdfUrl);
|
||||
|
||||
//当文件不存在时,就去下载
|
||||
if (!fileHandlerService.listConvertedFiles().containsKey(pdfName) || !ConfigConstants.isCacheEnabled()) {
|
||||
ReturnResponse<String> response = DownloadUtils.downLoad(fileAttribute, fileName);
|
||||
if (response.isFailure()) {
|
||||
return otherFilePreview.notSupportedFile(model, fileAttribute, response.getMsg());
|
||||
}
|
||||
String filePath = response.getContent();
|
||||
if (ConfigConstants.isCacheEnabled()) {
|
||||
// 加入缓存
|
||||
fileHandlerService.addConvertedFile(pdfName, fileHandlerService.getRelativePath(outFilePath));
|
||||
}
|
||||
if(ConvertPicUtil.convertJpg2Pdf(filePath, outFilePath)){
|
||||
model.addAttribute("pdfUrl", pdfName);
|
||||
return PDF_FILE_PREVIEW_PAGE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
model.addAttribute("pdfUrl", pdfName);
|
||||
return PDF_FILE_PREVIEW_PAGE;
|
||||
}
|
||||
|
||||
} else {
|
||||
File fileTiff = new File(strLocalTif);
|
||||
// 如果本地不存在这个tif文件,则下载
|
||||
if (!fileTiff.exists()) {
|
||||
ReturnResponse<String> response = DownloadUtils.downLoad(fileAttribute, fileName);
|
||||
if (response.isFailure()) {
|
||||
return otherFilePreview.notSupportedFile(model, fileAttribute, response.getMsg());
|
||||
}
|
||||
strLocalTif = response.getContent();
|
||||
}
|
||||
// 以JPG模式预览的过程
|
||||
String strJpgFilePathName = fileDir + inputFileNamePrefix + ".jpg";
|
||||
String strJpgFilePathName = fileDir + jpgName;
|
||||
// 将tif转换为jpg,返回转换后的文件路径、文件名的list
|
||||
List<String> listPic2Jpg = ConvertPicUtil.convertTif2Jpg(strLocalTif, strJpgFilePathName);
|
||||
// 将返回页面的图片url的list对象
|
||||
@@ -101,19 +91,11 @@ public class TiffFilePreviewImpl implements FilePreview {
|
||||
for (String strJpg : listPic2Jpg) {
|
||||
listImageUrls.add(baseUrl + strJpg);
|
||||
}
|
||||
|
||||
model.addAttribute("imgUrls", listImageUrls);
|
||||
model.addAttribute("currentUrl", listImageUrls.get(0));
|
||||
}
|
||||
|
||||
// 转换后的tif没用了,可以删掉了
|
||||
if (fileTiff.exists() && !fileTiff.delete()) {
|
||||
logger.error("{} 清理失败", strLocalTif);
|
||||
}
|
||||
|
||||
return PICTURE_FILE_PREVIEW_PAGE;
|
||||
}
|
||||
|
||||
return NOT_SUPPORTED_FILE_PAGE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
package cn.keking.utils;
|
||||
|
||||
|
||||
import com.lowagie.text.Document;
|
||||
import com.lowagie.text.Image;
|
||||
import com.lowagie.text.Rectangle;
|
||||
import com.lowagie.text.pdf.PdfWriter;
|
||||
import com.lowagie.text.pdf.RandomAccessFileOrArray;
|
||||
import com.lowagie.text.pdf.codec.TiffImage;
|
||||
import cn.keking.config.ConfigConstants;
|
||||
|
||||
import com.sun.media.jai.codec.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.itextpdf.text.Document;
|
||||
import com.itextpdf.text.Image;
|
||||
import com.itextpdf.text.io.FileChannelRandomAccessSource;
|
||||
import com.itextpdf.text.pdf.PdfWriter;
|
||||
import com.itextpdf.text.pdf.RandomAccessFileOrArray;
|
||||
import com.itextpdf.text.pdf.codec.TiffImage;
|
||||
import javax.media.jai.JAI;
|
||||
import javax.media.jai.RenderedOp;
|
||||
import java.awt.image.RenderedImage;
|
||||
@@ -18,13 +19,14 @@ import java.awt.image.renderable.ParameterBlock;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ConvertPicUtil {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(ConvertPicUtil.class);
|
||||
|
||||
private final static String fileDir = ConfigConstants.getFileDir();
|
||||
/**
|
||||
* Tif 转 JPG。
|
||||
*
|
||||
@@ -42,25 +44,21 @@ public class ConvertPicUtil {
|
||||
logger.info("找不到文件【" + strInputFile + "】");
|
||||
return null;
|
||||
}
|
||||
|
||||
strInputFile = strInputFile.replaceAll("\\\\", "/");
|
||||
strOutputFile = strOutputFile.replaceAll("\\\\", "/");
|
||||
|
||||
FileSeekableStream fileSeekStream = null;
|
||||
try {
|
||||
JPEGEncodeParam jpegEncodeParam = new JPEGEncodeParam();
|
||||
|
||||
TIFFEncodeParam tiffEncodeParam = new TIFFEncodeParam();
|
||||
tiffEncodeParam.setCompression(TIFFEncodeParam.COMPRESSION_GROUP4);
|
||||
tiffEncodeParam.setLittleEndian(false);
|
||||
|
||||
String strFilePrefix = strInputFile.substring(strInputFile.lastIndexOf("/") + 1, strInputFile.lastIndexOf("."));
|
||||
|
||||
String jpgname = strInputFile.replace(fileDir.replace("\\","/"), "");
|
||||
int index = jpgname.lastIndexOf(".");
|
||||
String strFilePrefix = jpgname.substring(0, index);
|
||||
fileSeekStream = new FileSeekableStream(strInputFile);
|
||||
ImageDecoder imageDecoder = ImageCodec.createImageDecoder("TIFF", fileSeekStream, null);
|
||||
int intTifCount = imageDecoder.getNumPages();
|
||||
logger.info("该tif文件共有【" + intTifCount + "】页");
|
||||
|
||||
String strJpgPath;
|
||||
String strJpgUrl;
|
||||
if (intTifCount == 1) {
|
||||
@@ -87,9 +85,7 @@ public class ConvertPicUtil {
|
||||
strJpg = strJpgPath + "/" + i + ".jpg";
|
||||
strJpgUrl = strFilePrefix + "/" + i + ".jpg";
|
||||
}
|
||||
|
||||
File fileJpg = new File(strJpg);
|
||||
|
||||
// 如果文件不存在,则生成
|
||||
if (!fileJpg.exists()) {
|
||||
RenderedImage renderedImage = imageDecoder.decodeAsRenderedImage(i);
|
||||
@@ -98,13 +94,11 @@ public class ConvertPicUtil {
|
||||
pb.add(fileJpg.toString());
|
||||
pb.add("JPEG");
|
||||
pb.add(jpegEncodeParam);
|
||||
|
||||
RenderedOp renderedOp = JAI.create("filestore", pb);
|
||||
renderedOp.dispose();
|
||||
|
||||
logger.info("每页分别保存至: " + fileJpg.getCanonicalPath());
|
||||
} else {
|
||||
logger.info("JPG文件已存在: " + fileJpg.getCanonicalPath());
|
||||
// logger.info("JPG文件已存在: " + fileJpg.getCanonicalPath());
|
||||
}
|
||||
|
||||
listImageFiles.add(strJpgUrl);
|
||||
@@ -131,101 +125,45 @@ public class ConvertPicUtil {
|
||||
* @param strJpgFile 输入的jpg的路径和文件名
|
||||
* @param strPdfFile 输出的pdf的路径和文件名
|
||||
*/
|
||||
public static void convertJpg2Pdf(String strJpgFile, String strPdfFile) {
|
||||
Document document = new Document();
|
||||
// 设置文档页边距
|
||||
document.setMargins(0, 0, 0, 0);
|
||||
|
||||
FileOutputStream fos = null;
|
||||
private static final int FIT_WIDTH = 500;
|
||||
private static final int FIT_HEIGHT = 900;
|
||||
public static boolean convertJpg2Pdf(String strJpgFile, String strPdfFile) {
|
||||
Document document= null;
|
||||
RandomAccessFileOrArray rafa = null;
|
||||
try {
|
||||
fos = new FileOutputStream(strPdfFile);
|
||||
PdfWriter.getInstance(document, fos);
|
||||
// 打开文档
|
||||
document = new Document();
|
||||
PdfWriter.getInstance(document, new FileOutputStream(strPdfFile));
|
||||
document.open();
|
||||
// 获取图片的宽高
|
||||
Image image = Image.getInstance(strJpgFile);
|
||||
float floatImageHeight = image.getScaledHeight();
|
||||
float floatImageWidth = image.getScaledWidth();
|
||||
// 设置页面宽高与图片一致
|
||||
Rectangle rectangle = new Rectangle(floatImageWidth, floatImageHeight);
|
||||
document.setPageSize(rectangle);
|
||||
// 图片居中
|
||||
image.setAlignment(Image.ALIGN_CENTER);
|
||||
//新建一页添加图片
|
||||
document.newPage();
|
||||
document.add(image);
|
||||
} catch (Exception ioe) {
|
||||
ioe.printStackTrace();
|
||||
} finally {
|
||||
//关闭文档
|
||||
rafa = new RandomAccessFileOrArray(new FileChannelRandomAccessSource(new RandomAccessFile(strJpgFile, "r").getChannel()));
|
||||
int pages = TiffImage.getNumberOfPages(rafa);
|
||||
Image image;
|
||||
for (int i = 1; i <= pages; i++) {
|
||||
try {
|
||||
image = TiffImage.getTiffImage(rafa, i);
|
||||
image.scaleToFit(FIT_WIDTH, FIT_HEIGHT);
|
||||
document.add(image);
|
||||
} catch (Exception e) {
|
||||
document.close();
|
||||
rafa.close();
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
document.close();
|
||||
rafa.close();
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.out.println("错误:"+ e.getMessage());
|
||||
}
|
||||
finally {
|
||||
document.close();
|
||||
try {
|
||||
assert fos != null;
|
||||
fos.flush();
|
||||
fos.close();
|
||||
rafa.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将Tif图片转换为Pdf文件(支持多页Tif)
|
||||
*
|
||||
* @param strTifFile 输入的tif的路径和文件名
|
||||
* @param strPdfFile 输出的pdf的路径和文件名
|
||||
* @return File
|
||||
*/
|
||||
public static File convertTif2Pdf(String strTifFile, String strPdfFile) {
|
||||
try {
|
||||
RandomAccessFileOrArray rafa = new RandomAccessFileOrArray(strTifFile);
|
||||
|
||||
Document document = new Document();
|
||||
// 设置文档页边距
|
||||
document.setMargins(0, 0, 0, 0);
|
||||
|
||||
PdfWriter.getInstance(document, new FileOutputStream(strPdfFile));
|
||||
document.open();
|
||||
int intPages = TiffImage.getNumberOfPages(rafa);
|
||||
Image image;
|
||||
File filePDF;
|
||||
|
||||
if (intPages == 1) {
|
||||
String strJpg = strTifFile.substring(0, strTifFile.lastIndexOf(".")) + ".jpg";
|
||||
File fileJpg = new File(strJpg);
|
||||
List<String> listPic2Jpg = convertTif2Jpg(strTifFile, strJpg);
|
||||
|
||||
if (listPic2Jpg != null && fileJpg.exists()) {
|
||||
convertJpg2Pdf(strJpg, strPdfFile);
|
||||
}
|
||||
|
||||
} else {
|
||||
for (int i = 1; i <= intPages; i++) {
|
||||
image = TiffImage.getTiffImage(rafa, i);
|
||||
// 设置页面宽高与图片一致
|
||||
Rectangle pageSize = new Rectangle(image.getScaledWidth(), image.getScaledHeight());
|
||||
document.setPageSize(pageSize);
|
||||
// 图片居中
|
||||
image.setAlignment(Image.ALIGN_CENTER);
|
||||
//新建一页添加图片
|
||||
document.newPage();
|
||||
document.add(image);
|
||||
}
|
||||
|
||||
document.close();
|
||||
}
|
||||
|
||||
rafa.close();
|
||||
|
||||
filePDF = new File(strPdfFile);
|
||||
|
||||
return filePDF;
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,16 +3,17 @@ package cn.keking.utils;
|
||||
import cn.keking.config.ConfigConstants;
|
||||
import cn.keking.model.FileAttribute;
|
||||
import cn.keking.model.ReturnResponse;
|
||||
import cn.keking.service.FileHandlerService;
|
||||
import io.mola.galimatias.GalimatiasParseException;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.util.HtmlUtils;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.UUID;
|
||||
|
||||
import static cn.keking.utils.KkFileUtils.isFtpUrl;
|
||||
@@ -36,13 +37,30 @@ public class DownloadUtils {
|
||||
*/
|
||||
public static ReturnResponse<String> downLoad(FileAttribute fileAttribute, String fileName) {
|
||||
// 忽略ssl证书
|
||||
String urlStr = null;
|
||||
String urlStrr = null;
|
||||
URL urll;
|
||||
try {
|
||||
SslUtils.ignoreSsl();
|
||||
urlStr = fileAttribute.getUrl().replaceAll("\\+", "%20");
|
||||
urll = new URL(urlStr);
|
||||
urlStrr = URLDecoder.decode(urll.getPath(), "UTF-8");
|
||||
} catch (Exception e) {
|
||||
logger.error("忽略SSL证书异常:", e);
|
||||
}
|
||||
String urlStr = fileAttribute.getUrl().replaceAll("\\+", "%20");
|
||||
ReturnResponse<String> response = new ReturnResponse<>(0, "下载成功!!!", "");
|
||||
if (!KkFileUtils.isAllowedUpload(fileName)) {
|
||||
response.setCode(1);
|
||||
response.setContent(null);
|
||||
response.setMsg("下载失败:不支持的类型!" + urlStr);
|
||||
return response;
|
||||
}
|
||||
assert urlStr != null;
|
||||
if (urlStr.contains("?fileKey=")) {
|
||||
response.setContent(fileDir + urlStrr);
|
||||
response.setMsg(fileName);
|
||||
return response;
|
||||
}
|
||||
String realPath = DownloadUtils.getRelFilePath(fileName, fileAttribute);
|
||||
if(!StringUtils.hasText(realPath)){
|
||||
response.setCode(1);
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package cn.keking.utils;
|
||||
|
||||
import cn.keking.config.ConfigConstants;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.util.HtmlUtils;
|
||||
|
||||
@@ -174,4 +176,19 @@ public class KkFileUtils {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断文件是否允许上传
|
||||
*
|
||||
* @param file 文件扩展名
|
||||
* @return 是否允许上传
|
||||
*/
|
||||
public static boolean isAllowedUpload(String file) {
|
||||
String fileType = suffixFromFileName(file);
|
||||
for (String type : ConfigConstants.getprohibit()) {
|
||||
if (type.equals(fileType))
|
||||
return false;
|
||||
}
|
||||
return !ObjectUtils.isEmpty(fileType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
130
server/src/main/java/cn/keking/utils/RarUtils.java
Normal file
130
server/src/main/java/cn/keking/utils/RarUtils.java
Normal file
@@ -0,0 +1,130 @@
|
||||
package cn.keking.utils;
|
||||
import cn.keking.config.ConfigConstants;
|
||||
import cn.keking.service.ZtreeNodeVo;
|
||||
import java.io.File;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author : Gao
|
||||
* create : 2023-04-08
|
||||
**/
|
||||
public class RarUtils {
|
||||
private static final String fileDir = ConfigConstants.getFileDir();
|
||||
|
||||
public static byte[] getUTF8BytesFromGBKString(String gbkStr) {
|
||||
int n = gbkStr.length();
|
||||
byte[] utfBytes = new byte[3 * n];
|
||||
int k = 0;
|
||||
for (int i = 0; i < n; i++) {
|
||||
int m = gbkStr.charAt(i);
|
||||
if (m < 128 && m >= 0) {
|
||||
utfBytes[k++] = (byte) m;
|
||||
continue;
|
||||
}
|
||||
utfBytes[k++] = (byte) (0xe0 | (m >> 12));
|
||||
utfBytes[k++] = (byte) (0x80 | ((m >> 6) & 0x3f));
|
||||
utfBytes[k++] = (byte) (0x80 | (m & 0x3f));
|
||||
}
|
||||
if (k < utfBytes.length) {
|
||||
byte[] tmp = new byte[k];
|
||||
System.arraycopy(utfBytes, 0, tmp, 0, k);
|
||||
return tmp;
|
||||
}
|
||||
return utfBytes;
|
||||
}
|
||||
|
||||
public static String getUtf8String(String str) {
|
||||
if (str != null && str.length() > 0) {
|
||||
String needEncodeCode = "ISO-8859-1";
|
||||
String neeEncodeCode = "ISO-8859-2";
|
||||
String gbkEncodeCode = "GBK";
|
||||
try {
|
||||
if (Charset.forName(needEncodeCode).newEncoder().canEncode(str)) {
|
||||
str = new String(str.getBytes(needEncodeCode), StandardCharsets.UTF_8);
|
||||
}
|
||||
if (Charset.forName(neeEncodeCode).newEncoder().canEncode(str)) {
|
||||
str = new String(str.getBytes(neeEncodeCode), StandardCharsets.UTF_8);
|
||||
}
|
||||
if (Charset.forName(gbkEncodeCode).newEncoder().canEncode(str)) {
|
||||
str = new String(getUTF8BytesFromGBKString(str), StandardCharsets.UTF_8);
|
||||
}
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
/**
|
||||
* 判断是否是中日韩文字
|
||||
*/
|
||||
private static boolean isChinese(char c) {
|
||||
Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
|
||||
return ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
|
||||
|| ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
|
||||
|| ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
|
||||
|| ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
|
||||
|| ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
|
||||
|| ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS;
|
||||
}
|
||||
public static boolean judge(char c){
|
||||
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z');
|
||||
}
|
||||
public static boolean isMessyCode(String strName) {
|
||||
//去除字符串中的空格 制表符 换行 回车
|
||||
Pattern p = Pattern.compile("\\s*|\t*|\r*|\n*");
|
||||
Matcher m = p.matcher(strName);
|
||||
String after = m.replaceAll("").replaceAll("\\+", "").replaceAll("#", "").replaceAll("&", "");
|
||||
//去除字符串中的标点符号
|
||||
String temp = after.replaceAll("\\p{P}", "");
|
||||
//处理之后转换成字符数组
|
||||
char[] ch = temp.trim().toCharArray();
|
||||
for (char c : ch) {
|
||||
//判断是否是数字或者英文字符
|
||||
if (!judge(c)) {
|
||||
//判断是否是中日韩文
|
||||
if (!isChinese(c)) {
|
||||
//如果不是数字或者英文字符也不是中日韩文则表示是乱码返回true
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
//表示不是乱码 返回false
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取文件目录树
|
||||
*/
|
||||
public static List<ZtreeNodeVo> getTree(String rootPath) {
|
||||
List<ZtreeNodeVo> nodes = new ArrayList<>();
|
||||
File file = new File(fileDir+rootPath);
|
||||
ZtreeNodeVo node = traverse(file);
|
||||
nodes.add(node);
|
||||
return nodes;
|
||||
}
|
||||
private static ZtreeNodeVo traverse(File file) {
|
||||
ZtreeNodeVo pathNodeVo = new ZtreeNodeVo();
|
||||
pathNodeVo.setId(file.getAbsolutePath().replace(fileDir, "").replace("\\", "/"));
|
||||
pathNodeVo.setName(file.getName());
|
||||
pathNodeVo.setPid(file.getParent().replace(fileDir, "").replace("\\", "/"));
|
||||
if (file.isDirectory()) {
|
||||
List<ZtreeNodeVo> subNodeVos = new ArrayList<>();
|
||||
File[] subFiles = file.listFiles();
|
||||
if (subFiles == null) {
|
||||
return pathNodeVo;
|
||||
}
|
||||
for (File subFile : subFiles) {
|
||||
ZtreeNodeVo subNodeVo = traverse(subFile);
|
||||
subNodeVos.add(subNodeVo);
|
||||
}
|
||||
pathNodeVo.setChildren(subNodeVos);
|
||||
}
|
||||
return pathNodeVo;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package cn.keking.web.controller;
|
||||
import cn.keking.config.ConfigConstants;
|
||||
import cn.keking.model.ReturnResponse;
|
||||
import cn.keking.utils.KkFileUtils;
|
||||
import cn.keking.utils.RarUtils;
|
||||
import cn.keking.utils.WebUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -20,12 +21,7 @@ import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author yudian-it
|
||||
@@ -40,7 +36,6 @@ public class FileController {
|
||||
private final String demoDir = "demo";
|
||||
private final String demoPath = demoDir + File.separator;
|
||||
public static final String BASE64_DECODE_ERROR_MSG = "Base64解码失败,请检查你的 %s 是否采用 Base64 + urlEncode 双重编码了!";
|
||||
private static final String[] not_allowed = { "dll", "exe", "msi" }; // 不允许上传的文件扩展名
|
||||
|
||||
@PostMapping("/fileUpload")
|
||||
public ReturnResponse<Object> fileUpload(@RequestParam("file") MultipartFile file) {
|
||||
@@ -64,12 +59,16 @@ public class FileController {
|
||||
}
|
||||
|
||||
@GetMapping("/deleteFile")
|
||||
public ReturnResponse<Object> deleteFile(String fileName) {
|
||||
public ReturnResponse<Object> deleteFile(String fileName,String password) {
|
||||
ReturnResponse<Object> checkResult = this.deleteFileCheck(fileName);
|
||||
if (checkResult.isFailure()) {
|
||||
return checkResult;
|
||||
}
|
||||
fileName = checkResult.getContent().toString();
|
||||
fileName = checkResult.getContent().toString();
|
||||
if(!ConfigConstants.getpassword().equalsIgnoreCase(password)){
|
||||
logger.error("删除文件【{}】失败,密码错误!",fileName);
|
||||
return ReturnResponse.failure("删除文件失败,密码错误!");
|
||||
}
|
||||
File file = new File(fileDir + demoPath + fileName);
|
||||
logger.info("删除文件:{}", file.getAbsolutePath());
|
||||
if (file.exists() && !file.delete()) {
|
||||
@@ -107,8 +106,10 @@ public class FileController {
|
||||
return ReturnResponse.failure("文件传接口已禁用");
|
||||
}
|
||||
String fileName = WebUtils.getFileNameFromMultipartFile(file);
|
||||
|
||||
if (!isAllowedUpload(fileName)) {
|
||||
if(fileName.lastIndexOf(".")==-1){
|
||||
return ReturnResponse.failure("不允许上传的类型");
|
||||
}
|
||||
if (!KkFileUtils.isAllowedUpload(fileName)) {
|
||||
return ReturnResponse.failure("不允许上传的文件类型: " + fileName);
|
||||
}
|
||||
if (KkFileUtils.isIllegalFileName(fileName)) {
|
||||
@@ -121,20 +122,6 @@ public class FileController {
|
||||
return ReturnResponse.success(fileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断文件是否允许上传
|
||||
*
|
||||
* @param file 文件扩展名
|
||||
* @return 是否允许上传
|
||||
*/
|
||||
private boolean isAllowedUpload(String file) {
|
||||
String fileType = KkFileUtils.suffixFromFileName(file);
|
||||
for (String type : not_allowed) {
|
||||
if (type.equals(fileType))
|
||||
return false;
|
||||
}
|
||||
return !ObjectUtils.isEmpty(fileType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除文件前校验
|
||||
@@ -162,6 +149,21 @@ public class FileController {
|
||||
return ReturnResponse.success(fileName);
|
||||
}
|
||||
|
||||
@GetMapping("/directory")
|
||||
public Object directory(String urls) {
|
||||
String fileUrl;
|
||||
try {
|
||||
fileUrl = WebUtils.decodeUrl(urls);
|
||||
} catch (Exception ex) {
|
||||
String errorMsg = String.format(BASE64_DECODE_ERROR_MSG, "url");
|
||||
return ReturnResponse.failure(errorMsg);
|
||||
}
|
||||
if (KkFileUtils.isIllegalFileName(fileUrl)) {
|
||||
return ReturnResponse.failure("不允许访问的路径:");
|
||||
}
|
||||
return RarUtils.getTree(fileUrl);
|
||||
}
|
||||
|
||||
private boolean existsFile(String fileName) {
|
||||
File file = new File(fileDir + demoPath + fileName);
|
||||
return file.exists();
|
||||
|
||||
@@ -40,6 +40,8 @@ public class AttributeSetFilter implements Filter {
|
||||
request.setAttribute("fileKey", httpRequest.getParameter("fileKey"));
|
||||
request.setAttribute("switchDisabled", ConfigConstants.getOfficePreviewSwitchDisabled());
|
||||
request.setAttribute("fileUploadDisable", ConfigConstants.getFileUploadDisable());
|
||||
request.setAttribute("BeiAn", ConfigConstants.getBeiAn());
|
||||
request.setAttribute("size", ConfigConstants.maxsize());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|_|\_\ |_|\_\ |_| |_| |_| \___| \/ |_| \___| \_/\_/
|
||||
|
||||
=> Spring Boot :: ${spring-boot.version}
|
||||
=> kkFileView :: 4.2.0-SNAPSHOT
|
||||
=> kkFileView :: 4.2.0
|
||||
=> Home site :: https://kkview.cn
|
||||
=> Github :: https://github.com/kekingcn/kkFileView
|
||||
=> Gitee :: https://gitee.com/kekingcn/file-online-preview
|
||||
|
||||
@@ -1,8 +1 @@
|
||||
/**
|
||||
* Minified by jsDelivr using Terser v5.3.5.
|
||||
* Original file: /npm/js-base64@3.6.0/base64.js
|
||||
*
|
||||
* Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
|
||||
*/
|
||||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):function(){const r=e.Base64,o=t();o.noConflict=()=>(e.Base64=r,o),e.Meteor&&(Base64=o),e.Base64=o}()}("undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:this,(function(){"use strict";const e="3.6.0",t="function"==typeof atob,r="function"==typeof btoa,o="function"==typeof Buffer,n="function"==typeof TextDecoder?new TextDecoder:void 0,a="function"==typeof TextEncoder?new TextEncoder:void 0,f=[..."ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="],i=(e=>{let t={};return e.forEach(((e,r)=>t[e]=r)),t})(f),c=/^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/,u=String.fromCharCode.bind(String),s="function"==typeof Uint8Array.from?Uint8Array.from.bind(Uint8Array):(e,t=(e=>e))=>new Uint8Array(Array.prototype.slice.call(e,0).map(t)),d=e=>e.replace(/[+\/]/g,(e=>"+"==e?"-":"_")).replace(/=+$/m,""),l=e=>e.replace(/[^A-Za-z0-9\+\/]/g,""),h=e=>{let t,r,o,n,a="";const i=e.length%3;for(let i=0;i<e.length;){if((r=e.charCodeAt(i++))>255||(o=e.charCodeAt(i++))>255||(n=e.charCodeAt(i++))>255)throw new TypeError("invalid character found");t=r<<16|o<<8|n,a+=f[t>>18&63]+f[t>>12&63]+f[t>>6&63]+f[63&t]}return i?a.slice(0,i-3)+"===".substring(i):a},p=r?e=>btoa(e):o?e=>Buffer.from(e,"binary").toString("base64"):h,y=o?e=>Buffer.from(e).toString("base64"):e=>{let t=[];for(let r=0,o=e.length;r<o;r+=4096)t.push(u.apply(null,e.subarray(r,r+4096)));return p(t.join(""))},A=(e,t=!1)=>t?d(y(e)):y(e),b=e=>{if(e.length<2)return(t=e.charCodeAt(0))<128?e:t<2048?u(192|t>>>6)+u(128|63&t):u(224|t>>>12&15)+u(128|t>>>6&63)+u(128|63&t);var t=65536+1024*(e.charCodeAt(0)-55296)+(e.charCodeAt(1)-56320);return u(240|t>>>18&7)+u(128|t>>>12&63)+u(128|t>>>6&63)+u(128|63&t)},g=/[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g,B=e=>e.replace(g,b),x=o?e=>Buffer.from(e,"utf8").toString("base64"):a?e=>y(a.encode(e)):e=>p(B(e)),C=(e,t=!1)=>t?d(x(e)):x(e),m=e=>C(e,!0),U=/[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g,F=e=>{switch(e.length){case 4:var t=((7&e.charCodeAt(0))<<18|(63&e.charCodeAt(1))<<12|(63&e.charCodeAt(2))<<6|63&e.charCodeAt(3))-65536;return u(55296+(t>>>10))+u(56320+(1023&t));case 3:return u((15&e.charCodeAt(0))<<12|(63&e.charCodeAt(1))<<6|63&e.charCodeAt(2));default:return u((31&e.charCodeAt(0))<<6|63&e.charCodeAt(1))}},w=e=>e.replace(U,F),S=e=>{if(e=e.replace(/\s+/g,""),!c.test(e))throw new TypeError("malformed base64.");e+="==".slice(2-(3&e.length));let t,r,o,n="";for(let a=0;a<e.length;)t=i[e.charAt(a++)]<<18|i[e.charAt(a++)]<<12|(r=i[e.charAt(a++)])<<6|(o=i[e.charAt(a++)]),n+=64===r?u(t>>16&255):64===o?u(t>>16&255,t>>8&255):u(t>>16&255,t>>8&255,255&t);return n},E=t?e=>atob(l(e)):o?e=>Buffer.from(e,"base64").toString("binary"):S,v=o?e=>s(Buffer.from(e,"base64")):e=>s(E(e),(e=>e.charCodeAt(0))),D=e=>v(z(e)),R=o?e=>Buffer.from(e,"base64").toString("utf8"):n?e=>n.decode(v(e)):e=>w(E(e)),z=e=>l(e.replace(/[-_]/g,(e=>"-"==e?"+":"/"))),T=e=>R(z(e)),Z=e=>({value:e,enumerable:!1,writable:!0,configurable:!0}),j=function(){const e=(e,t)=>Object.defineProperty(String.prototype,e,Z(t));e("fromBase64",(function(){return T(this)})),e("toBase64",(function(e){return C(this,e)})),e("toBase64URI",(function(){return C(this,!0)})),e("toBase64URL",(function(){return C(this,!0)})),e("toUint8Array",(function(){return D(this)}))},I=function(){const e=(e,t)=>Object.defineProperty(Uint8Array.prototype,e,Z(t));e("toBase64",(function(e){return A(this,e)})),e("toBase64URI",(function(){return A(this,!0)})),e("toBase64URL",(function(){return A(this,!0)}))},O={version:e,VERSION:"3.6.0",atob:E,atobPolyfill:S,btoa:p,btoaPolyfill:h,fromBase64:T,toBase64:C,encode:C,encodeURI:m,encodeURL:m,utob:B,btou:w,decode:T,isValid:e=>{if("string"!=typeof e)return!1;const t=e.replace(/\s+/g,"").replace(/=+$/,"");return!/[^\s0-9a-zA-Z\+/]/.test(t)||!/[^\s0-9a-zA-Z\-_]/.test(t)},fromUint8Array:A,toUint8Array:D,extendString:j,extendUint8Array:I,extendBuiltins:()=>{j(),I()},Base64:{}};return Object.keys(O).forEach((e=>O.Base64[e]=O[e])),O}));
|
||||
//# sourceMappingURL=/sm/8bca8602e2256d240cef904e1c1df432ccfdd2a2a73f6911c60be79e526e3e1e.map
|
||||
(function(global,factory){typeof exports==="object"&&typeof module!=="undefined"?module.exports=factory(global):typeof define==="function"&&define.amd?define(factory):factory(global)}((typeof self!=="undefined"?self:typeof window!=="undefined"?window:typeof global!=="undefined"?global:this),function(global){global=global||{};var _Base64=global.Base64;var version="2.6.3";var b64chars="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";var b64tab=function(bin){var t={};for(var i=0,l=bin.length;i<l;i++){t[bin.charAt(i)]=i}return t}(b64chars);var fromCharCode=String.fromCharCode;var cb_utob=function(c){if(c.length<2){var cc=c.charCodeAt(0);return cc<128?c:cc<2048?(fromCharCode(192|(cc>>>6))+fromCharCode(128|(cc&63))):(fromCharCode(224|((cc>>>12)&15))+fromCharCode(128|((cc>>>6)&63))+fromCharCode(128|(cc&63)))}else{var cc=65536+(c.charCodeAt(0)-55296)*1024+(c.charCodeAt(1)-56320);return(fromCharCode(240|((cc>>>18)&7))+fromCharCode(128|((cc>>>12)&63))+fromCharCode(128|((cc>>>6)&63))+fromCharCode(128|(cc&63)))}};var re_utob=/[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g;var utob=function(u){return u.replace(re_utob,cb_utob)};var cb_encode=function(ccc){var padlen=[0,2,1][ccc.length%3],ord=ccc.charCodeAt(0)<<16|((ccc.length>1?ccc.charCodeAt(1):0)<<8)|((ccc.length>2?ccc.charCodeAt(2):0)),chars=[b64chars.charAt(ord>>>18),b64chars.charAt((ord>>>12)&63),padlen>=2?"=":b64chars.charAt((ord>>>6)&63),padlen>=1?"=":b64chars.charAt(ord&63)];return chars.join("")};var btoa=global.btoa&&typeof global.btoa=="function"?function(b){return global.btoa(b)}:function(b){if(b.match(/[^\x00-\xFF]/)){throw new RangeError("The string contains invalid characters.")}return b.replace(/[\s\S]{1,3}/g,cb_encode)};var _encode=function(u){return btoa(utob(String(u)))};var mkUriSafe=function(b64){return b64.replace(/[+\/]/g,function(m0){return m0=="+"?"-":"_"}).replace(/=/g,"")};var encode=function(u,urisafe){return urisafe?mkUriSafe(_encode(u)):_encode(u)};var encodeURI=function(u){return encode(u,true)};var fromUint8Array;if(global.Uint8Array){fromUint8Array=function(a,urisafe){var b64="";for(var i=0,l=a.length;i<l;i+=3){var a0=a[i],a1=a[i+1],a2=a[i+2];var ord=a0<<16|a1<<8|a2;b64+=b64chars.charAt(ord>>>18)+b64chars.charAt((ord>>>12)&63)+(typeof a1!="undefined"?b64chars.charAt((ord>>>6)&63):"=")+(typeof a2!="undefined"?b64chars.charAt(ord&63):"=")}return urisafe?mkUriSafe(b64):b64}}var re_btou=/[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g;var cb_btou=function(cccc){switch(cccc.length){case 4:var cp=((7&cccc.charCodeAt(0))<<18)|((63&cccc.charCodeAt(1))<<12)|((63&cccc.charCodeAt(2))<<6)|(63&cccc.charCodeAt(3)),offset=cp-65536;return(fromCharCode((offset>>>10)+55296)+fromCharCode((offset&1023)+56320));case 3:return fromCharCode(((15&cccc.charCodeAt(0))<<12)|((63&cccc.charCodeAt(1))<<6)|(63&cccc.charCodeAt(2)));default:return fromCharCode(((31&cccc.charCodeAt(0))<<6)|(63&cccc.charCodeAt(1)))}};var btou=function(b){return b.replace(re_btou,cb_btou)};var cb_decode=function(cccc){var len=cccc.length,padlen=len%4,n=(len>0?b64tab[cccc.charAt(0)]<<18:0)|(len>1?b64tab[cccc.charAt(1)]<<12:0)|(len>2?b64tab[cccc.charAt(2)]<<6:0)|(len>3?b64tab[cccc.charAt(3)]:0),chars=[fromCharCode(n>>>16),fromCharCode((n>>>8)&255),fromCharCode(n&255)];chars.length-=[0,0,2,1][padlen];return chars.join("")};var _atob=global.atob&&typeof global.atob=="function"?function(a){return global.atob(a)}:function(a){return a.replace(/\S{1,4}/g,cb_decode)};var atob=function(a){return _atob(String(a).replace(/[^A-Za-z0-9\+\/]/g,""))};var _decode=function(a){return btou(_atob(a))};var _fromURI=function(a){return String(a).replace(/[-_]/g,function(m0){return m0=="-"?"+":"/"}).replace(/[^A-Za-z0-9\+\/]/g,"")};var decode=function(a){return _decode(_fromURI(a))};var toUint8Array;if(global.Uint8Array){toUint8Array=function(a){return Uint8Array.from(atob(_fromURI(a)),function(c){return c.charCodeAt(0)})}}var noConflict=function(){var Base64=global.Base64;global.Base64=_Base64;return Base64};global.Base64={VERSION:version,atob:atob,btoa:btoa,fromBase64:decode,toBase64:encode,utob:utob,encode:encode,encodeURI:encodeURI,btou:btou,decode:decode,noConflict:noConflict,fromUint8Array:fromUint8Array,toUint8Array:toUint8Array};if(typeof Object.defineProperty==="function"){var noEnum=function(v){return{value:v,enumerable:false,writable:true,configurable:true}};global.Base64.extendString=function(){Object.defineProperty(String.prototype,"fromBase64",noEnum(function(){return decode(this)}));Object.defineProperty(String.prototype,"toBase64",noEnum(function(urisafe){return encode(this,urisafe)}));Object.defineProperty(String.prototype,"toBase64URI",noEnum(function(){return encode(this,true)}))}}if(global["Meteor"]){Base64=global.Base64}if(typeof module!=="undefined"&&module.exports){module.exports.Base64=global.Base64}else{if(typeof define==="function"&&define.amd){define([],function(){return global.Base64})}}return{Base64:global.Base64}}));
|
||||
@@ -25685,7 +25685,7 @@
|
||||
if (!e)
|
||||
return t;
|
||||
if (!g || "" == y) {
|
||||
var r, i = 10, o = l(e.pages);
|
||||
var r, i = e.pages.length, o = l(e.pages);
|
||||
try {
|
||||
for (o.s(); !(r = o.n()).done; ) {
|
||||
var a = r.value
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -10,18 +10,15 @@
|
||||
<meta name=keywords content="Xmind,mindmap,mind map,mind mapping,mind mapping software,free mind mapping software,work from home,WFH,remote">
|
||||
<link rel=stylesheet href=css/bootstrap-customized-2821153174.min.css>
|
||||
<link rel=stylesheet href=css/index-5376440060.css>
|
||||
<script src=js/jquery-3-c9f5aeeca3.2.1.min.js> </script>
|
||||
<script src="../js/jquery-3.6.1.min.js"></script>
|
||||
<meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
|
||||
<link rel=stylesheet href=css/share-embed-39eba5407f.css> </head>
|
||||
<body>
|
||||
<script>
|
||||
window.manifests={snowbrush:"js/snowbrush.js"},window.metadataString=""
|
||||
</script>
|
||||
<script src=js/text-autospace-fed758f4a6.min.js> </script>
|
||||
<script src=js/polyfill-45b9836beb.min.js> </script>
|
||||
<script src=js/js-cookie-a978ac7394.js> </script>
|
||||
<script src=js/popper-135fa9e662.min.js> </script>
|
||||
<script src=js/bootstrap-26779614c4.min.js> </script>
|
||||
<script src=js/base.61517cade8.js> </script>
|
||||
<script src=js/share-embed.68f7476360.js> </script>
|
||||
</body>
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,108 +1,71 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en">
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1.0">
|
||||
<#include "*/commonHeader.ftl">
|
||||
<script src="js/jquery-3.6.1.min.js" type="text/javascript"></script>
|
||||
<link href="css/zTreeStyle.css" rel="stylesheet" type="text/css">
|
||||
<script src="js/base64.min.js" type="text/javascript"></script>
|
||||
<style type="text/css">
|
||||
<meta charset="utf-8"/>
|
||||
<title>压缩包预览</title>
|
||||
<script src="js/jquery-3.6.1.min.js"></script>
|
||||
<#include "*/commonHeader.ftl">
|
||||
<script src="js/base64.min.js" type="text/javascript"></script>
|
||||
<link href="css/zTreeStyle.css" rel="stylesheet" type="text/css">
|
||||
<script type="text/javascript" src="js/jquery.ztree.core.js"></script>
|
||||
<style type="text/css">
|
||||
body {
|
||||
background-color: #404040;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {color: #2f332a;font-weight: bold;font-family: Helvetica, Arial, sans-serif;padding-bottom: 5px;}
|
||||
h1 {font-size: 24px;line-height: 34px;text-align: center;}
|
||||
h2 {font-size: 14px;line-height: 24px;padding-top: 5px;}
|
||||
h6 {font-weight: normal;font-size: 12px;letter-spacing: 1px;line-height: 24px;text-align: center;}
|
||||
a {color:#3C6E31;text-decoration: underline;}
|
||||
a:hover {background-color:#3C6E31;color:white;}
|
||||
code {color: #2f332a;}
|
||||
div.zTreeDemoBackground {width:600px;text-align:center;margin: 0 auto;background-color: #ffffff;}
|
||||
div.zTreeDemoBackground {
|
||||
max-width: 880px;
|
||||
text-align:center;
|
||||
margin:0 auto;
|
||||
border-radius:3px;
|
||||
box-shadow:rgba(0,0,0,0.15) 0 0 8px;
|
||||
background:#FBFBFB;
|
||||
border:1px solid #ddd;
|
||||
margin:1px auto;
|
||||
padding:5px;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="zTreeDemoBackground left">
|
||||
<h1>kkFileView</h1>
|
||||
<ul id="treeDemo" class="ztree"></ul>
|
||||
</div>
|
||||
<script type="text/javascript" src="js/jquery.ztree.core.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
const data = JSON.parse('${fileTree}');
|
||||
var baseUrl = "${baseUrl}";
|
||||
var setting = {
|
||||
view: {
|
||||
fontCss : {"color":"blue"},
|
||||
showLine: true
|
||||
},
|
||||
<script>
|
||||
var settings = {
|
||||
data: {
|
||||
key: {
|
||||
children: 'childList',
|
||||
name: 'originName'
|
||||
simpleData: {
|
||||
enable: true, //true 、 false 分别表示 使用 、 不使用 简单数据模式
|
||||
idKey: "id", //节点数据中保存唯一标识的属性名称
|
||||
pIdKey: "pid", //节点数据中保存其父节点唯一标识的属性名称
|
||||
rootPId: ""
|
||||
}
|
||||
},
|
||||
callback:{
|
||||
beforeClick:function (treeId, treeNode, clickFlag) {
|
||||
console.log("节点参数:treeId-" + treeId + "treeNode-"
|
||||
+ JSON.stringify(treeNode) + "clickFlag-" + clickFlag);
|
||||
},
|
||||
onClick:function (event, treeId, treeNode) {
|
||||
if (!treeNode.directory) {
|
||||
/**实现窗口最大化**/
|
||||
var fulls = "left=0,screenX=0,top=0,screenY=0,scrollbars=1"; //定义弹出窗口的参数
|
||||
if (window.screen) {
|
||||
var ah = screen.availHeight - 30;
|
||||
var aw = (screen.availWidth - 10) / 2;
|
||||
fulls += ",height=" + ah;
|
||||
fulls += ",innerHeight=" + ah;
|
||||
fulls += ",width=" + aw;
|
||||
fulls += ",innerWidth=" + aw;
|
||||
fulls += ",resizable"
|
||||
} else {
|
||||
fulls += ",resizable"; // 对于不支持screen属性的浏览器,可以手工进行最大化。 manually
|
||||
}
|
||||
var previewUrl = baseUrl + treeNode.fileName +"?fileKey="+ treeNode.fileKey;
|
||||
window.open("onlinePreview?url=" + encodeURIComponent(Base64.encode(previewUrl)), "_blank",fulls);
|
||||
}
|
||||
}
|
||||
callback: {
|
||||
onClick: chooseNode,
|
||||
}
|
||||
};
|
||||
var height = 0;
|
||||
$(document).ready(function(){
|
||||
var treeObj = $.fn.zTree.init($("#treeDemo"), setting, data);
|
||||
treeObj.expandAll(true);
|
||||
height = getZtreeDomHeight();
|
||||
$(".zTreeDemoBackground").css("height", height);
|
||||
|
||||
function chooseNode(event, treeId, treeNode) {
|
||||
var path = '${baseUrl}' + treeNode.id +"?fileKey="+'${fileName}';
|
||||
location.href = "${baseUrl}onlinePreview?url=" + encodeURIComponent(Base64.encode(path));
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
var url = '${fileTree}';
|
||||
$.ajax({
|
||||
type: "get",
|
||||
url: "${baseUrl}directory?urls="+encodeURIComponent(Base64.encode(url)),
|
||||
success: function (res) {
|
||||
zTreeObj = $.fn.zTree.init($("#treeDemo"), settings, res); //初始化树
|
||||
zTreeObj.expandAll(true); //true 节点全部展开、false节点收缩
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/*初始化水印*/
|
||||
window.onload = function() {
|
||||
initWaterMark();
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算ztreedom的高度
|
||||
*/
|
||||
function getZtreeDomHeight() {
|
||||
return $("#treeDemo").height() > window.document.documentElement.clientHeight - 1
|
||||
? $("#treeDemo").height() : window.document.documentElement.clientHeight - 1;
|
||||
}
|
||||
/**
|
||||
* 页面变化调整高度
|
||||
*/
|
||||
window.onresize = function(){
|
||||
height = getZtreeDomHeight();
|
||||
$(".zTreeDemoBackground").css("height", height);
|
||||
}
|
||||
/**
|
||||
* 滚动时调整高度
|
||||
*/
|
||||
window.onscroll = function(){
|
||||
height = getZtreeDomHeight();
|
||||
$(".zTreeDemoBackground").css("height", height);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@@ -116,33 +116,10 @@
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<#if fileUploadDisable == false>
|
||||
<div style="padding: 10px">
|
||||
<div style="padding: 10px" >
|
||||
<form enctype="multipart/form-data" id="fileUpload">
|
||||
<div class="form-group">
|
||||
<p id="fileName"></p>
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<button type="button" class="btn btn-default" id="fileSelectBtn" style="margin-bottom:8px">
|
||||
<span class="glyphicon glyphicon-cloud-upload" aria-hidden="true"></span> 选择文件
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<button id="btnSubmit" type="button" class="btn btn-success">上 传</button>
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="file" name="file" style="display: none" id="fileSelect"
|
||||
onchange="onFileSelected()"/>
|
||||
<div class="alert alert-danger alert-dismissable hide" role="alert" id="postFileAlert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<strong>请选择需要上传的文件!</strong>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="file" id="size" name="file"/>
|
||||
<input type="button" id="btnSubmit" value=" 上 传 "/>
|
||||
</form>
|
||||
</div>
|
||||
</#if>
|
||||
@@ -175,22 +152,34 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: grid; place-items: center;">
|
||||
<div>
|
||||
<a target="_blank" href="https://beian.miit.gov.cn/" >${BeiAn}</a>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function deleteFile(fileName) {
|
||||
$.ajax({
|
||||
url: '${baseUrl}deleteFile?fileName=' + fileName,
|
||||
success: function (data) {
|
||||
// 删除完成,刷新table
|
||||
if (1 === data.code) {
|
||||
alert(data.msg);
|
||||
} else {
|
||||
$('#table').bootstrapTable('refresh', {});
|
||||
function deleteFile(fileName,password) {
|
||||
if(window.confirm('你确定要删除文件吗?')){
|
||||
password = prompt("请输入默认密码:123456");
|
||||
$.ajax({
|
||||
url: '${baseUrl}deleteFile?fileName=' + fileName +'&password='+password,
|
||||
success: function (data) {
|
||||
// console.log(data);
|
||||
// 删除完成,刷新table
|
||||
if ("删除文件失败,密码错误!" === data.msg) {
|
||||
alert(data.msg);
|
||||
} else {
|
||||
$('#table').bootstrapTable('refresh', {});
|
||||
}
|
||||
},
|
||||
error: function (data) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
error: function (data) {
|
||||
console.log(data);
|
||||
}
|
||||
})
|
||||
})
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function showLoadingDiv() {
|
||||
@@ -238,7 +227,8 @@
|
||||
}).on('pre-body.bs.table', function (e, data) {
|
||||
// 每个data添加一列用来操作
|
||||
$(data).each(function (index, item) {
|
||||
item.action = "<a class='btn btn-success' target='_blank' href='${baseUrl}onlinePreview?url=" + encodeURIComponent(Base64.encode('${baseUrl}' + item.fileName)) + "'>预览</a>";
|
||||
item.action = "<a class='btn btn-success' target='_blank' href='${baseUrl}onlinePreview?url=" + encodeURIComponent(Base64.encode('${baseUrl}' + item.fileName)) + "'>预览</a>" +
|
||||
"<a class='btn btn-danger' style='margin-left:10px;' href='javascript:void(0);' onclick='deleteFile(\"" + encodeURIComponent(Base64.encode('${baseUrl}' + item.fileName)) + "\")'>删除</a>";
|
||||
});
|
||||
return data;
|
||||
}).on('post-body.bs.table', function (e, data) {
|
||||
@@ -265,20 +255,9 @@
|
||||
});
|
||||
|
||||
$("#btnSubmit").click(function () {
|
||||
var _fileName = $("#fileName").text()
|
||||
var index = _fileName.lastIndexOf(".");
|
||||
//获取后缀
|
||||
var ext = _fileName.substr(index + 1);
|
||||
if (!ext || ext == "dll" || ext == "exe" || ext == "msi") {
|
||||
window.alert(ext + "不支持上传")
|
||||
return;
|
||||
}
|
||||
if (!_fileName) {
|
||||
$("#postFileAlert").addClass("show");
|
||||
window.setTimeout(function () {
|
||||
$("#postFileAlert").removeClass("show");
|
||||
}, 3000);//显示的时间
|
||||
return;
|
||||
var filepath = $("#size").val();
|
||||
if(!checkFileSize(filepath)){
|
||||
return false;
|
||||
}
|
||||
showLoadingDiv();
|
||||
$("#fileUpload").ajaxSubmit({
|
||||
@@ -294,7 +273,6 @@
|
||||
},
|
||||
error: function () {
|
||||
alert('上传失败,请联系管理员');
|
||||
$("#fileName").text("");
|
||||
$(".loading_container").hide();
|
||||
},
|
||||
url: 'fileUpload', /*设置post提交到的页面*/
|
||||
@@ -303,6 +281,37 @@
|
||||
});
|
||||
});
|
||||
});
|
||||
function checkFileSize(filepath) {
|
||||
var daxiao= "${size}";
|
||||
daxiao= daxiao.replace("MB","");
|
||||
// console.log(daxiao)
|
||||
var maxsize = daxiao * 1024 * 1024;
|
||||
var errMsg = "上传的文件不能超过${size}喔!!!";
|
||||
var tipMsg = "您的浏览器暂不支持上传,确保上传文件不要超过${size},建议使用IE、FireFox、Chrome浏览器";
|
||||
try {
|
||||
var filesize = 0;
|
||||
var ua = window.navigator.userAgent;
|
||||
if (ua.indexOf("MSIE") >= 1) {
|
||||
//IE
|
||||
var img = new Image();
|
||||
img.src = filepath;
|
||||
filesize = img.fileSize;
|
||||
} else {
|
||||
filesize = $("#size")[0].files[0].size; //byte
|
||||
}
|
||||
if (filesize > 0 && filesize > maxsize) {
|
||||
alert(errMsg);
|
||||
return false;
|
||||
} else if (filesize == -1) {
|
||||
alert(tipMsg);
|
||||
return false;
|
||||
}
|
||||
} catch (e) {
|
||||
alert("上传失败,请重试");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -46,6 +46,47 @@
|
||||
<div class="page-header">
|
||||
<h1>版本发布记录</h1>
|
||||
</div>
|
||||
<div class="panel panel-success">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">2023年04月13日,v4.2.0 版本</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div>
|
||||
1. 新增 SVG 格式文件预览支持<br>
|
||||
2. 新增加密的 Office 文件预览支持<br>
|
||||
3. 新增加密的 zip、rar 等压缩包文件预览支持<br>
|
||||
4. 新增 xmind 软件模型文件预览支持<br>
|
||||
5. 新增 bpmn 工作流模型文件预览支持<br>
|
||||
6. 新增 eml 邮件文件预览支持<br>
|
||||
7. 新增 epub 电子书文件预览支持<br>
|
||||
8. 新增 dotm,ett,xlt,xltm,wpt,dot,xlam,xla,dotx 等格式的办公文档预览支持<br>
|
||||
9. 新增 obj, 3ds, stl, ply, gltf, glb, off, 3dm, fbx, dae, wrl, 3mf, ifc, brep, step, iges, fcstd, bim 等 3D 模型文件预览支持<br>
|
||||
10. 新增可配置限制高风险文件上传的功能,比如 exe 文件<br>
|
||||
11. 新增可配置站点的备案信息<br>
|
||||
12. 新增演示站点删除文件需要密码的功能<br>
|
||||
13. 文本文档预览加入缓存<br>
|
||||
14. 美化 404、500 报错页<br>
|
||||
15. 优化发票等 ofd 文件预览的印证渲染兼容性<br>
|
||||
16. 移除 office-plugin 模块, 使用新版 jodconverter组件<br>
|
||||
17. 优化 Excel 文件的预览效果<br>
|
||||
18. 优化 CAD 文件的预览效果<br>
|
||||
19. 更新 xstream 、junrar、pdfbox 等依赖的版本<br>
|
||||
20. 更新 TIF 文件转换 PDF 的插件,添加转换缓存<br>
|
||||
21. 优化演示页 UI 部署<br>
|
||||
22. 压缩包文件预览支持目录<br>
|
||||
23. 修复部分接口 XSS 问题<br>
|
||||
24. 修复控制台打印的演示地址不跟着 content-path 配置走的问题<br>
|
||||
25. 修复 ofd 文件预览跨域问题<br>
|
||||
26. 修复内部自签证书 https 协议 url 文件无法下载的问题<br>
|
||||
27. 修复特殊符号的文件无法删除的问题<br>
|
||||
28. 修复 PDF 转图片,内存无法回收导致的 OOM<br>
|
||||
29. 修复 xlsx7.4 以上版本文件预览乱码的问题<br>
|
||||
30. 修复 TrustHostFilter 未拦截跨域接口的问题,这是一个安全问题,有使用到 TrustHost 功能的务必升级<br>
|
||||
31. 修复压缩包文件预览在 Linux 系统下文件名乱码的问题<br>
|
||||
32. 修复 ofd 文件预览页码只能显示 10 页的问题<br>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-success">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">2022年12月14日,v4.1.0 版本</h3>
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
</div>
|
||||
|
||||
<!-- JavaSript ================================================== -->
|
||||
<script src="pptx/jquery-3.5.1.min.js"></script>
|
||||
<script src="js/jquery-3.6.1.min.js"></script>
|
||||
<script src="pptx/jquery.contextMenu.js?v=11.2.5_20210128"></script>
|
||||
<script src="pptx/idocv/idocv_common.min.js"></script>
|
||||
<script src="pptx/jquery.mobile-events.min.js"></script>
|
||||
|
||||
Reference in New Issue
Block a user