mirror of
https://github.com/kekingcn/kkFileView.git
synced 2026-03-30 20:32:54 +00:00
Compare commits
1 Commits
urlencodin
...
office
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b066d8dbf |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -27,6 +27,5 @@ nbdist/
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
server/src/main/cache/
|
||||
server/src/main/file/
|
||||
server/src/main/log
|
||||
jodconverter-web/src/main/cache/
|
||||
jodconverter-web/src/main/file/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
FROM ubuntu:20.04
|
||||
MAINTAINER chenjh "842761733@qq.com"
|
||||
ADD server/target/kkFileView-*.tar.gz /opt/
|
||||
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 &&\
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>cn.keking</groupId>
|
||||
<artifactId>office-plugin</artifactId>
|
||||
<artifactId>jodconverter-core</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
<properties>
|
||||
@@ -19,7 +19,6 @@ import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.artofsolving.jodconverter.util.ConfigUtils;
|
||||
import org.artofsolving.jodconverter.util.PlatformUtils;
|
||||
|
||||
import com.sun.star.beans.PropertyValue;
|
||||
@@ -56,7 +55,7 @@ public class OfficeUtils {
|
||||
Map<String,Object> subProperties = (Map<String,Object>) value;
|
||||
value = toUnoProperties(subProperties);
|
||||
}
|
||||
propertyValues[i++] = property(entry.getKey(), value);
|
||||
propertyValues[i++] = property((String) entry.getKey(), value);
|
||||
}
|
||||
return propertyValues;
|
||||
}
|
||||
@@ -69,7 +68,7 @@ public class OfficeUtils {
|
||||
|
||||
public static File getDefaultOfficeHome() {
|
||||
Properties properties = new Properties();
|
||||
String customizedConfigPath = ConfigUtils.getCustomizedConfigPath();
|
||||
String customizedConfigPath = getCustomizedConfigPath();
|
||||
try {
|
||||
BufferedReader bufferedReader = new BufferedReader(new FileReader(customizedConfigPath));
|
||||
properties.load(bufferedReader);
|
||||
@@ -81,7 +80,7 @@ public class OfficeUtils {
|
||||
}
|
||||
if (PlatformUtils.isWindows()) {
|
||||
// %ProgramFiles(x86)% on 64-bit machines; %ProgramFiles% on 32-bit ones
|
||||
String homePath = ConfigUtils.getHomePath();
|
||||
String homePath = OfficeUtils.getHomePath();
|
||||
String programFiles = System.getenv("ProgramFiles(x86)");
|
||||
if (programFiles == null) {
|
||||
programFiles = System.getenv("ProgramFiles");
|
||||
@@ -128,7 +127,30 @@ public class OfficeUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static String getHomePath() {
|
||||
String userDir = System.getenv("KKFILEVIEW_BIN_FOLDER");
|
||||
if (userDir == null) {
|
||||
userDir = System.getProperty("user.dir");
|
||||
}
|
||||
if (userDir.endsWith("bin")) {
|
||||
userDir = userDir.substring(0, userDir.length() - 4);
|
||||
} else {
|
||||
String separator = File.separator;
|
||||
if (userDir.contains("jodconverter-web")) {
|
||||
userDir = userDir + separator + "src" + separator + "main";
|
||||
} else {
|
||||
userDir = userDir + separator + "jodconverter-web" + separator + "src" + separator + "main";
|
||||
}
|
||||
}
|
||||
return userDir;
|
||||
}
|
||||
|
||||
public static String getCustomizedConfigPath() {
|
||||
String homePath = OfficeUtils.getHomePath();
|
||||
String separator = java.io.File.separator;
|
||||
String configFilePath = homePath + separator + "config" + separator + "application.properties";
|
||||
return configFilePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* SpringBoot application.properties 支持从环境变量获取值
|
||||
@@ -14,12 +14,12 @@
|
||||
<artifactId>kkFileView</artifactId>
|
||||
<version>2.2.1</version>
|
||||
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<!-- required for org.hyperic:sigar -->
|
||||
@@ -35,18 +35,12 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jetty</artifactId>
|
||||
<groupId>net.logstash.logback</groupId>
|
||||
<artifactId>logstash-logback-encoder</artifactId>
|
||||
<version>4.11</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
@@ -54,7 +48,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.keking</groupId>
|
||||
<artifactId>office-plugin</artifactId>
|
||||
<artifactId>jodconverter-core</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -166,6 +160,11 @@
|
||||
<artifactId>xstream</artifactId>
|
||||
<version>1.4.15</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>19.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.googlecode.concurrentlinkedhashmap</groupId>
|
||||
<artifactId>concurrentlinkedhashmap-lru</artifactId>
|
||||
@@ -193,14 +192,6 @@
|
||||
<scope>system</scope>
|
||||
<systemPath>${basedir}/lib/aspose-cad-19.9.jar</systemPath>
|
||||
</dependency>
|
||||
<!-- 编码识别 -->
|
||||
<dependency>
|
||||
<groupId>cpdetector</groupId>
|
||||
<artifactId>cpdetector</artifactId>
|
||||
<version>1.04</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${basedir}/lib/cpdetector-1.04.jar</systemPath>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<resources>
|
||||
@@ -1,13 +1,5 @@
|
||||
[#ftl]
|
||||
[#-- @implicitly included --]
|
||||
[#-- @ftlvariable name="baseUrl" type="java.lang.String" --]
|
||||
[#-- @ftlvariable name="imgUrls" type="String" --]
|
||||
[#-- @ftlvariable name="textData" type="java.lang.String" --]
|
||||
[#-- @ftlvariable name="xmlContent" type="java.lang.String" --]
|
||||
[#-- @ftlvariable name="textContent" type="java.lang.String" --]
|
||||
[#-- @ftlvariable name="textType" type="java.lang.String" --]
|
||||
[#-- @ftlvariable name="markdown" type="String" --]
|
||||
[#-- @ftlvariable name="xml" type="String" --]
|
||||
[#-- @ftlvariable name="switchDisabled" type="String" --]
|
||||
[#-- @ftlvariable name="imgurls" type="String" --]
|
||||
[#-- @ftlvariable name="watermarkAngle" type="String" --]
|
||||
@@ -8,15 +8,8 @@ import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
@SpringBootApplication
|
||||
@EnableScheduling
|
||||
@ComponentScan(value = "cn.keking.*")
|
||||
public class ServerMain {
|
||||
|
||||
public class FilePreviewApplication {
|
||||
public static void main(String[] args) {
|
||||
ServerMain.staticInitSystemProperty();
|
||||
SpringApplication.run(ServerMain.class, args);
|
||||
}
|
||||
|
||||
private static void staticInitSystemProperty(){
|
||||
//pdfbox兼容低版本jdk
|
||||
System.setProperty("sun.java2d.cmm", "sun.java2d.cmm.kcms.KcmsServiceProvider");
|
||||
SpringApplication.run(FilePreviewApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package cn.keking.config;
|
||||
|
||||
import org.artofsolving.jodconverter.util.ConfigUtils;
|
||||
import org.artofsolving.jodconverter.office.OfficeUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -25,7 +25,7 @@ public class ConfigConstants {
|
||||
private static String FTP_PASSWORD;
|
||||
private static String FTP_CONTROL_ENCODING;
|
||||
private static String BASE_URL;
|
||||
private static String FILE_DIR = ConfigUtils.getHomePath() + File.separator + "file" + File.separator;
|
||||
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;
|
||||
|
||||
@@ -158,7 +158,7 @@ public class ConfigConstants {
|
||||
}
|
||||
|
||||
public static void setFileDirValue(String fileDir) {
|
||||
if (!DEFAULT_FILE_DIR_VALUE.equalsIgnoreCase(fileDir)) {
|
||||
if (!DEFAULT_FILE_DIR_VALUE.equals(fileDir.toLowerCase())) {
|
||||
if (!fileDir.endsWith(File.separator)) {
|
||||
fileDir = fileDir + File.separator;
|
||||
}
|
||||
@@ -173,7 +173,7 @@ public class ConfigConstants {
|
||||
|
||||
public static void setTrustHostValue(String trustHost) {
|
||||
CopyOnWriteArraySet<String> trustHostSet;
|
||||
if (DEFAULT_TRUST_HOST.equalsIgnoreCase(trustHost)) {
|
||||
if (DEFAULT_TRUST_HOST.equals(trustHost.toLowerCase())) {
|
||||
trustHostSet = new CopyOnWriteArraySet<>();
|
||||
} else {
|
||||
String[] trustHostArray = trustHost.toLowerCase().split(",");
|
||||
@@ -207,11 +207,9 @@ public class ConfigConstants {
|
||||
public static String getOfficePreviewSwitchDisabled() {
|
||||
return OFFICE_PREVIEW_SWITCH_DISABLED;
|
||||
}
|
||||
|
||||
@Value("${office.preview.switch.disabled:true}")
|
||||
public void setOfficePreviewSwitchDisabled(String officePreviewSwitchDisabled) {
|
||||
OFFICE_PREVIEW_SWITCH_DISABLED = officePreviewSwitchDisabled;
|
||||
}
|
||||
public static void setOfficePreviewSwitchDisabledValue(String officePreviewSwitchDisabled) {
|
||||
public static void setOfficePreviewSwitchDisabled(String officePreviewSwitchDisabled) {
|
||||
OFFICE_PREVIEW_SWITCH_DISABLED = officePreviewSwitchDisabled;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,6 @@
|
||||
package cn.keking.service;
|
||||
package cn.keking.config;
|
||||
|
||||
import cn.keking.config.ConfigConstants;
|
||||
import cn.keking.config.WatermarkConfigConstants;
|
||||
import org.artofsolving.jodconverter.office.OfficeUtils;
|
||||
import org.artofsolving.jodconverter.util.ConfigUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -45,7 +42,7 @@ public class ConfigRefreshComponent {
|
||||
String ftpUsername;
|
||||
String ftpPassword;
|
||||
String ftpControlEncoding;
|
||||
String configFilePath = ConfigUtils.getCustomizedConfigPath();
|
||||
String configFilePath = OfficeUtils.getCustomizedConfigPath();
|
||||
String baseUrl;
|
||||
String trustHost;
|
||||
String pdfDownloadDisable;
|
||||
@@ -76,7 +73,7 @@ public class ConfigRefreshComponent {
|
||||
ConfigConstants.setFtpControlEncodingValue(ftpControlEncoding);
|
||||
ConfigConstants.setBaseUrlValue(baseUrl);
|
||||
ConfigConstants.setTrustHostValue(trustHost);
|
||||
ConfigConstants.setOfficePreviewSwitchDisabledValue(officePreviewSwitchDisabled);
|
||||
ConfigConstants.setOfficePreviewSwitchDisabled(officePreviewSwitchDisabled);
|
||||
ConfigConstants.setPdfDownloadDisableValue(pdfDownloadDisable);
|
||||
setWatermarkConfig(properties);
|
||||
bufferedReader.close();
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
package cn.keking.model;
|
||||
|
||||
import cn.keking.config.ConfigConstants;
|
||||
|
||||
/**
|
||||
* Created by kl on 2018/1/17.
|
||||
* Content :
|
||||
@@ -9,11 +7,12 @@ import cn.keking.config.ConfigConstants;
|
||||
public class FileAttribute {
|
||||
|
||||
private FileType type;
|
||||
|
||||
private String suffix;
|
||||
|
||||
private String name;
|
||||
|
||||
private String url;
|
||||
private String fileKey;
|
||||
private String officePreviewType = ConfigConstants.getOfficePreviewType();
|
||||
|
||||
public FileAttribute() {
|
||||
}
|
||||
@@ -25,30 +24,6 @@ public class FileAttribute {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public FileAttribute(FileType type, String suffix, String name, String url, String officePreviewType) {
|
||||
this.type = type;
|
||||
this.suffix = suffix;
|
||||
this.name = name;
|
||||
this.url = url;
|
||||
this.officePreviewType = officePreviewType;
|
||||
}
|
||||
|
||||
public String getFileKey() {
|
||||
return fileKey;
|
||||
}
|
||||
|
||||
public void setFileKey(String fileKey) {
|
||||
this.fileKey = fileKey;
|
||||
}
|
||||
|
||||
public String getOfficePreviewType() {
|
||||
return officePreviewType;
|
||||
}
|
||||
|
||||
public void setOfficePreviewType(String officePreviewType) {
|
||||
this.officePreviewType = officePreviewType;
|
||||
}
|
||||
|
||||
public FileType getType() {
|
||||
return type;
|
||||
}
|
||||
29
jodconverter-web/src/main/java/cn/keking/model/FileType.java
Normal file
29
jodconverter-web/src/main/java/cn/keking/model/FileType.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package cn.keking.model;
|
||||
|
||||
/**
|
||||
* Created by kl on 2018/1/17.
|
||||
* Content :文件类型,文本,office,压缩包等等
|
||||
*/
|
||||
public enum FileType {
|
||||
picture("picturefilepreviewimpl"),
|
||||
compress("compressFilePreviewImpl"),
|
||||
office("officeFilePreviewImpl"),
|
||||
simText("simTextFilePreviewImpl"),
|
||||
pdf("pdfFilePreviewImpl"),
|
||||
other("otherFilePreviewImpl"),
|
||||
media("mediaFilePreviewImpl"),
|
||||
markdown("markdownFilePreviewImpl"),
|
||||
cad("cadFilePreviewImpl");
|
||||
|
||||
|
||||
private final String instanceName;
|
||||
|
||||
FileType(String instanceName){
|
||||
this.instanceName=instanceName;
|
||||
}
|
||||
|
||||
public String getInstanceName() {
|
||||
return instanceName;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,6 +3,7 @@ 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;
|
||||
@@ -19,36 +20,44 @@ import java.util.concurrent.Executors;
|
||||
public class FileConvertQueueTask {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(getClass());
|
||||
private final FilePreviewFactory previewFactory;
|
||||
private final CacheService cacheService;
|
||||
private final FileHandlerService fileHandlerService;
|
||||
|
||||
public FileConvertQueueTask(FilePreviewFactory previewFactory, CacheService cacheService, FileHandlerService fileHandlerService) {
|
||||
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.fileHandlerService = fileHandlerService;
|
||||
this.fileUtils=fileUtils;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void startTask(){
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(1);
|
||||
executorService.submit(new ConvertTask(previewFactory, cacheService, fileHandlerService));
|
||||
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 FileHandlerService fileHandlerService;
|
||||
|
||||
private final FileUtils fileUtils;
|
||||
|
||||
public ConvertTask(FilePreviewFactory previewFactory,
|
||||
CacheService cacheService,
|
||||
FileHandlerService fileHandlerService) {
|
||||
FileUtils fileUtils) {
|
||||
this.previewFactory = previewFactory;
|
||||
this.cacheService = cacheService;
|
||||
this.fileHandlerService = fileHandlerService;
|
||||
this.fileUtils=fileUtils;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -58,7 +67,7 @@ public class FileConvertQueueTask {
|
||||
try {
|
||||
url = cacheService.takeQueueTask();
|
||||
if(url != null){
|
||||
FileAttribute fileAttribute = fileHandlerService.getFileAttribute(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)) {
|
||||
@@ -5,10 +5,7 @@ import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
|
||||
import com.googlecode.concurrentlinkedhashmap.Weighers;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
@@ -24,78 +21,15 @@ import java.util.concurrent.BlockingQueue;
|
||||
public class CacheServiceJDKImpl implements CacheService {
|
||||
|
||||
private Map<String, String> pdfCache;
|
||||
|
||||
private Map<String, List<String>> imgCache;
|
||||
|
||||
private Map<String, Integer> pdfImagesCache;
|
||||
|
||||
private static final int QUEUE_SIZE = 500000;
|
||||
|
||||
private final BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(QUEUE_SIZE);
|
||||
|
||||
@PostConstruct
|
||||
public void initCache(){
|
||||
initPDFCachePool(CacheService.DEFAULT_PDF_CAPACITY);
|
||||
initIMGCachePool(CacheService.DEFAULT_IMG_CAPACITY);
|
||||
initPdfImagesCachePool(CacheService.DEFAULT_PDFIMG_CAPACITY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putPDFCache(String key, String value) {
|
||||
pdfCache.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putImgCache(String key, List<String> value) {
|
||||
imgCache.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getPDFCache() {
|
||||
return pdfCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPDFCache(String key) {
|
||||
return pdfCache.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> getImgCache() {
|
||||
return imgCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getImgCache(String key) {
|
||||
if(StringUtils.isEmpty(key)){
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return imgCache.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPdfImageCache(String key) {
|
||||
return pdfImagesCache.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putPdfImageCache(String pdfFilePath, int 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
|
||||
public void addQueueTask(String url) {
|
||||
blockingQueue.add(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String takeQueueTask() throws InterruptedException {
|
||||
return blockingQueue.take();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initPDFCachePool(Integer capacity) {
|
||||
pdfCache = new ConcurrentLinkedHashMap.Builder<String, String>()
|
||||
@@ -116,4 +50,85 @@ public class CacheServiceJDKImpl implements CacheService {
|
||||
.maximumWeightedCapacity(capacity).weigher(Weighers.singleton())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putPDFCache(String key, String value) {
|
||||
if (pdfCache == null) {
|
||||
initPDFCachePool(CacheService.DEFAULT_PDF_CAPACITY);
|
||||
}
|
||||
pdfCache.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putImgCache(String key, List<String> value) {
|
||||
if (imgCache == null) {
|
||||
initIMGCachePool(CacheService.DEFAULT_IMG_CAPACITY);
|
||||
}
|
||||
imgCache.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getPDFCache() {
|
||||
if (pdfCache == null) {
|
||||
initPDFCachePool(CacheService.DEFAULT_PDF_CAPACITY);
|
||||
}
|
||||
return pdfCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPDFCache(String key) {
|
||||
if (pdfCache == null) {
|
||||
initPDFCachePool(CacheService.DEFAULT_PDF_CAPACITY);
|
||||
}
|
||||
return pdfCache.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> getImgCache() {
|
||||
if (imgCache == null) {
|
||||
initPDFCachePool(CacheService.DEFAULT_IMG_CAPACITY);
|
||||
}
|
||||
return imgCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getImgCache(String key) {
|
||||
if (imgCache == null) {
|
||||
initPDFCachePool(CacheService.DEFAULT_IMG_CAPACITY);
|
||||
}
|
||||
return imgCache.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPdfImageCache(String key) {
|
||||
if (pdfImagesCache == null) {
|
||||
initPdfImagesCachePool(CacheService.DEFAULT_PDFIMG_CAPACITY);
|
||||
}
|
||||
return pdfImagesCache.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putPdfImageCache(String pdfFilePath, int num) {
|
||||
if (pdfImagesCache == null) {
|
||||
initPdfImagesCachePool(CacheService.DEFAULT_PDFIMG_CAPACITY);
|
||||
}
|
||||
pdfImagesCache.put(pdfFilePath, num);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanCache() {
|
||||
initPDFCachePool(CacheService.DEFAULT_PDF_CAPACITY);
|
||||
initIMGCachePool(CacheService.DEFAULT_IMG_CAPACITY);
|
||||
initPdfImagesCachePool(CacheService.DEFAULT_PDFIMG_CAPACITY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addQueueTask(String url) {
|
||||
blockingQueue.add(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String takeQueueTask() throws InterruptedException {
|
||||
return blockingQueue.take();
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package cn.keking.service.cache.impl;
|
||||
|
||||
import cn.keking.service.cache.CacheService;
|
||||
import org.artofsolving.jodconverter.util.ConfigUtils;
|
||||
import org.artofsolving.jodconverter.office.OfficeUtils;
|
||||
import org.rocksdb.RocksDB;
|
||||
import org.rocksdb.RocksDBException;
|
||||
import org.slf4j.Logger;
|
||||
@@ -30,7 +30,7 @@ public class CacheServiceRocksDBImpl implements CacheService {
|
||||
RocksDB.loadLibrary();
|
||||
}
|
||||
|
||||
private static final String DB_PATH = ConfigUtils.getHomePath() + File.separator + "cache";
|
||||
private static final String DB_PATH = OfficeUtils.getHomePath() + File.separator + "cache";
|
||||
|
||||
private static final int QUEUE_SIZE = 500000;
|
||||
|
||||
@@ -6,7 +6,7 @@ import cn.keking.model.ReturnResponse;
|
||||
import cn.keking.service.FilePreview;
|
||||
import cn.keking.utils.CadUtils;
|
||||
import cn.keking.utils.DownloadUtils;
|
||||
import cn.keking.service.FileHandlerService;
|
||||
import cn.keking.utils.FileUtils;
|
||||
import cn.keking.utils.PdfUtils;
|
||||
import cn.keking.web.filter.BaseUrlFilter;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -22,12 +22,20 @@ import static cn.keking.service.impl.OfficeFilePreviewImpl.getPreviewType;
|
||||
@Service
|
||||
public class CadFilePreviewImpl implements FilePreview {
|
||||
|
||||
private final FileHandlerService fileHandlerService;
|
||||
private final FileUtils fileUtils;
|
||||
|
||||
private final DownloadUtils downloadUtils;
|
||||
|
||||
private final CadUtils cadUtils;
|
||||
|
||||
private final PdfUtils pdfUtils;
|
||||
|
||||
public CadFilePreviewImpl(FileHandlerService fileHandlerService, CadUtils cadUtils, PdfUtils pdfUtils) {
|
||||
this.fileHandlerService = fileHandlerService;
|
||||
public CadFilePreviewImpl(FileUtils fileUtils,
|
||||
DownloadUtils downloadUtils,
|
||||
CadUtils cadUtils,
|
||||
PdfUtils pdfUtils) {
|
||||
this.fileUtils = fileUtils;
|
||||
this.downloadUtils = downloadUtils;
|
||||
this.cadUtils = cadUtils;
|
||||
this.pdfUtils = pdfUtils;
|
||||
|
||||
@@ -48,9 +56,9 @@ public class CadFilePreviewImpl implements FilePreview {
|
||||
String pdfName = fileName.substring(0, fileName.lastIndexOf(".") + 1) + "pdf";
|
||||
String outFilePath = FILE_DIR + pdfName;
|
||||
// 判断之前是否已转换过,如果转换过,直接返回,否则执行转换
|
||||
if (!fileHandlerService.listConvertedFiles().containsKey(pdfName) || !ConfigConstants.isCacheEnabled()) {
|
||||
if (!fileUtils.listConvertedFiles().containsKey(pdfName) || !ConfigConstants.isCacheEnabled()) {
|
||||
String filePath;
|
||||
ReturnResponse<String> response = DownloadUtils.downLoad(fileAttribute, null);
|
||||
ReturnResponse<String> response = downloadUtils.downLoad(fileAttribute, null);
|
||||
if (0 != response.getCode()) {
|
||||
model.addAttribute("fileType", suffix);
|
||||
model.addAttribute("msg", response.getMsg());
|
||||
@@ -66,7 +74,7 @@ public class CadFilePreviewImpl implements FilePreview {
|
||||
}
|
||||
if (ConfigConstants.isCacheEnabled()) {
|
||||
// 加入缓存
|
||||
fileHandlerService.addConvertedFile(pdfName, fileHandlerService.getRelativePath(outFilePath));
|
||||
fileUtils.addConvertedFile(pdfName, fileUtils.getRelativePath(outFilePath));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,8 @@ import cn.keking.model.FileAttribute;
|
||||
import cn.keking.model.ReturnResponse;
|
||||
import cn.keking.service.FilePreview;
|
||||
import cn.keking.utils.DownloadUtils;
|
||||
import cn.keking.service.FileHandlerService;
|
||||
import cn.keking.service.CompressFileReader;
|
||||
import cn.keking.utils.FileUtils;
|
||||
import cn.keking.utils.ZipReader;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -18,12 +18,18 @@ import org.springframework.util.StringUtils;
|
||||
@Service
|
||||
public class CompressFilePreviewImpl implements FilePreview {
|
||||
|
||||
private final FileHandlerService fileHandlerService;
|
||||
private final CompressFileReader compressFileReader;
|
||||
private final FileUtils fileUtils;
|
||||
|
||||
public CompressFilePreviewImpl(FileHandlerService fileHandlerService, CompressFileReader compressFileReader) {
|
||||
this.fileHandlerService = fileHandlerService;
|
||||
this.compressFileReader = compressFileReader;
|
||||
private final DownloadUtils downloadUtils;
|
||||
|
||||
private final ZipReader zipReader;
|
||||
|
||||
public CompressFilePreviewImpl(FileUtils fileUtils,
|
||||
DownloadUtils downloadUtils,
|
||||
ZipReader zipReader) {
|
||||
this.fileUtils = fileUtils;
|
||||
this.downloadUtils = downloadUtils;
|
||||
this.zipReader = zipReader;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -32,8 +38,8 @@ public class CompressFilePreviewImpl implements FilePreview {
|
||||
String suffix=fileAttribute.getSuffix();
|
||||
String fileTree = null;
|
||||
// 判断文件名是否存在(redis缓存读取)
|
||||
if (!StringUtils.hasText(fileHandlerService.getConvertedFile(fileName)) || !ConfigConstants.isCacheEnabled()) {
|
||||
ReturnResponse<String> response = DownloadUtils.downLoad(fileAttribute, fileName);
|
||||
if (!StringUtils.hasText(fileUtils.getConvertedFile(fileName)) || !ConfigConstants.isCacheEnabled()) {
|
||||
ReturnResponse<String> response = downloadUtils.downLoad(fileAttribute, fileName);
|
||||
if (0 != response.getCode()) {
|
||||
model.addAttribute("fileType", suffix);
|
||||
model.addAttribute("msg", response.getMsg());
|
||||
@@ -41,17 +47,17 @@ public class CompressFilePreviewImpl implements FilePreview {
|
||||
}
|
||||
String filePath = response.getContent();
|
||||
if ("zip".equalsIgnoreCase(suffix) || "jar".equalsIgnoreCase(suffix) || "gzip".equalsIgnoreCase(suffix)) {
|
||||
fileTree = compressFileReader.readZipFile(filePath, fileName);
|
||||
fileTree = zipReader.readZipFile(filePath, fileName);
|
||||
} else if ("rar".equalsIgnoreCase(suffix)) {
|
||||
fileTree = compressFileReader.unRar(filePath, fileName);
|
||||
fileTree = zipReader.unRar(filePath, fileName);
|
||||
} else if ("7z".equalsIgnoreCase(suffix)) {
|
||||
fileTree = compressFileReader.read7zFile(filePath, fileName);
|
||||
fileTree = zipReader.read7zFile(filePath, fileName);
|
||||
}
|
||||
if (fileTree != null && !"null".equals(fileTree) && ConfigConstants.isCacheEnabled()) {
|
||||
fileHandlerService.addConvertedFile(fileName, fileTree);
|
||||
fileUtils.addConvertedFile(fileName, fileTree);
|
||||
}
|
||||
} else {
|
||||
fileTree = fileHandlerService.getConvertedFile(fileName);
|
||||
fileTree = fileUtils.getConvertedFile(fileName);
|
||||
}
|
||||
if (fileTree != null && !"null".equals(fileTree)) {
|
||||
model.addAttribute("fileTree", fileTree);
|
||||
@@ -5,8 +5,6 @@ import cn.keking.service.FilePreview;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.ui.Model;
|
||||
|
||||
import static com.sun.glass.ui.Clipboard.TEXT_TYPE;
|
||||
|
||||
/**
|
||||
* @author kl (http://kailing.pub)
|
||||
* @since 2020/12/25
|
||||
@@ -23,7 +21,7 @@ public class MarkdownFilePreviewImpl implements FilePreview {
|
||||
|
||||
@Override
|
||||
public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
|
||||
model.addAttribute(TEXT_TYPE,"markdown");
|
||||
model.addAttribute("markdown","true");
|
||||
return simTextFilePreview.filePreviewHandle(url, model, fileAttribute);
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import cn.keking.model.FileAttribute;
|
||||
import cn.keking.model.ReturnResponse;
|
||||
import cn.keking.service.FilePreview;
|
||||
import cn.keking.utils.DownloadUtils;
|
||||
import cn.keking.service.FileHandlerService;
|
||||
import cn.keking.utils.FileUtils;
|
||||
import cn.keking.web.filter.BaseUrlFilter;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.ui.Model;
|
||||
@@ -17,23 +17,27 @@ import org.springframework.ui.Model;
|
||||
@Service
|
||||
public class MediaFilePreviewImpl implements FilePreview {
|
||||
|
||||
private final FileHandlerService fileHandlerService;
|
||||
private final DownloadUtils downloadUtils;
|
||||
|
||||
public MediaFilePreviewImpl(FileHandlerService fileHandlerService) {
|
||||
this.fileHandlerService = fileHandlerService;
|
||||
private final FileUtils fileUtils;
|
||||
|
||||
public MediaFilePreviewImpl(DownloadUtils downloadUtils,
|
||||
FileUtils fileUtils) {
|
||||
this.downloadUtils = downloadUtils;
|
||||
this.fileUtils = fileUtils;
|
||||
}
|
||||
|
||||
@Override
|
||||
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());
|
||||
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() + fileHandlerService.getRelativePath(response.getContent()));
|
||||
model.addAttribute("mediaUrl", BaseUrlFilter.getBaseUrl() + fileUtils.getRelativePath(response.getContent()));
|
||||
}
|
||||
} else {
|
||||
model.addAttribute("mediaUrl", url);
|
||||
@@ -5,8 +5,8 @@ import cn.keking.model.FileAttribute;
|
||||
import cn.keking.model.ReturnResponse;
|
||||
import cn.keking.service.FilePreview;
|
||||
import cn.keking.utils.DownloadUtils;
|
||||
import cn.keking.service.FileHandlerService;
|
||||
import cn.keking.service.OfficeToPdfService;
|
||||
import cn.keking.utils.FileUtils;
|
||||
import cn.keking.utils.OfficeToPdf;
|
||||
import cn.keking.utils.PdfUtils;
|
||||
import cn.keking.web.filter.BaseUrlFilter;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -22,14 +22,22 @@ import java.util.List;
|
||||
@Service
|
||||
public class OfficeFilePreviewImpl implements FilePreview {
|
||||
|
||||
private final FileHandlerService fileHandlerService;
|
||||
private final PdfUtils pdfUtils;
|
||||
private final OfficeToPdfService officeToPdfService;
|
||||
private final FileUtils fileUtils;
|
||||
|
||||
public OfficeFilePreviewImpl(FileHandlerService fileHandlerService, PdfUtils pdfUtils, OfficeToPdfService officeToPdfService) {
|
||||
this.fileHandlerService = fileHandlerService;
|
||||
private final PdfUtils pdfUtils;
|
||||
|
||||
private final DownloadUtils downloadUtils;
|
||||
|
||||
private final OfficeToPdf officeToPdf;
|
||||
|
||||
public OfficeFilePreviewImpl(FileUtils fileUtils,
|
||||
PdfUtils pdfUtils,
|
||||
DownloadUtils downloadUtils,
|
||||
OfficeToPdf officeToPdf) {
|
||||
this.fileUtils = fileUtils;
|
||||
this.pdfUtils = pdfUtils;
|
||||
this.officeToPdfService = officeToPdfService;
|
||||
this.downloadUtils = downloadUtils;
|
||||
this.officeToPdf = officeToPdf;
|
||||
}
|
||||
|
||||
public static final String OFFICE_PREVIEW_TYPE_IMAGE = "image";
|
||||
@@ -39,17 +47,18 @@ public class OfficeFilePreviewImpl implements FilePreview {
|
||||
@Override
|
||||
public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
|
||||
// 预览Type,参数传了就取参数的,没传取系统默认
|
||||
String officePreviewType = fileAttribute.getOfficePreviewType();
|
||||
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();
|
||||
boolean isHtml = suffix.equalsIgnoreCase("xls") || suffix.equalsIgnoreCase("xlsx");
|
||||
String pdfName = fileName.substring(0, fileName.lastIndexOf(".") + 1) + (isHtml ? "html" : "pdf");
|
||||
String outFilePath = FILE_DIR + pdfName;
|
||||
model.addAttribute("switchDisabled", ConfigConstants.getOfficePreviewSwitchDisabled());
|
||||
// 判断之前是否已转换过,如果转换过,直接返回,否则执行转换
|
||||
if (!fileHandlerService.listConvertedFiles().containsKey(pdfName) || !ConfigConstants.isCacheEnabled()) {
|
||||
if (!fileUtils.listConvertedFiles().containsKey(pdfName) || !ConfigConstants.isCacheEnabled()) {
|
||||
String filePath;
|
||||
ReturnResponse<String> response = DownloadUtils.downLoad(fileAttribute, null);
|
||||
ReturnResponse<String> response = downloadUtils.downLoad(fileAttribute, null);
|
||||
if (0 != response.getCode()) {
|
||||
model.addAttribute("fileType", suffix);
|
||||
model.addAttribute("msg", response.getMsg());
|
||||
@@ -57,14 +66,14 @@ public class OfficeFilePreviewImpl implements FilePreview {
|
||||
}
|
||||
filePath = response.getContent();
|
||||
if (StringUtils.hasText(outFilePath)) {
|
||||
officeToPdfService.openOfficeToPDF(filePath, outFilePath);
|
||||
officeToPdf.openOfficeToPDF(filePath, outFilePath);
|
||||
if (isHtml) {
|
||||
// 对转换后的文件进行操作(改变编码方式)
|
||||
fileHandlerService.doActionConvertedFile(outFilePath);
|
||||
fileUtils.doActionConvertedFile(outFilePath);
|
||||
}
|
||||
if (ConfigConstants.isCacheEnabled()) {
|
||||
// 加入缓存
|
||||
fileHandlerService.addConvertedFile(pdfName, fileHandlerService.getRelativePath(outFilePath));
|
||||
fileUtils.addConvertedFile(pdfName, fileUtils.getRelativePath(outFilePath));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import cn.keking.model.FileAttribute;
|
||||
import cn.keking.model.ReturnResponse;
|
||||
import cn.keking.service.FilePreview;
|
||||
import cn.keking.utils.DownloadUtils;
|
||||
import cn.keking.service.FileHandlerService;
|
||||
import cn.keking.utils.FileUtils;
|
||||
import cn.keking.utils.PdfUtils;
|
||||
import cn.keking.web.filter.BaseUrlFilter;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -20,27 +20,35 @@ import java.util.List;
|
||||
@Service
|
||||
public class PdfFilePreviewImpl implements FilePreview {
|
||||
|
||||
private final FileHandlerService fileHandlerService;
|
||||
private final FileUtils fileUtils;
|
||||
|
||||
private final PdfUtils pdfUtils;
|
||||
|
||||
private final DownloadUtils downloadUtils;
|
||||
|
||||
private static final String FILE_DIR = ConfigConstants.getFileDir();
|
||||
|
||||
public PdfFilePreviewImpl(FileHandlerService fileHandlerService, PdfUtils pdfUtils) {
|
||||
this.fileHandlerService = fileHandlerService;
|
||||
public PdfFilePreviewImpl(FileUtils fileUtils,
|
||||
PdfUtils pdfUtils,
|
||||
DownloadUtils downloadUtils) {
|
||||
this.fileUtils = fileUtils;
|
||||
this.pdfUtils = pdfUtils;
|
||||
this.downloadUtils = downloadUtils;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
|
||||
String suffix=fileAttribute.getSuffix();
|
||||
String fileName=fileAttribute.getName();
|
||||
String officePreviewType = fileAttribute.getOfficePreviewType();
|
||||
String officePreviewType = model.asMap().get("officePreviewType") == null ? ConfigConstants.getOfficePreviewType() : model.asMap().get("officePreviewType").toString();
|
||||
String baseUrl = BaseUrlFilter.getBaseUrl();
|
||||
String pdfName = fileName.substring(0, fileName.lastIndexOf(".") + 1) + "pdf";
|
||||
String outFilePath = FILE_DIR + pdfName;
|
||||
model.addAttribute("switchDisabled", ConfigConstants.getOfficePreviewSwitchDisabled());
|
||||
if (OfficeFilePreviewImpl.OFFICE_PREVIEW_TYPE_IMAGE.equals(officePreviewType) || OfficeFilePreviewImpl.OFFICE_PREVIEW_TYPE_ALL_IMAGES.equals(officePreviewType)) {
|
||||
//当文件不存在时,就去下载
|
||||
if (!fileHandlerService.listConvertedFiles().containsKey(pdfName) || !ConfigConstants.isCacheEnabled()) {
|
||||
ReturnResponse<String> response = DownloadUtils.downLoad(fileAttribute, fileName);
|
||||
if (!fileUtils.listConvertedFiles().containsKey(pdfName) || !ConfigConstants.isCacheEnabled()) {
|
||||
ReturnResponse<String> response = downloadUtils.downLoad(fileAttribute, fileName);
|
||||
if (0 != response.getCode()) {
|
||||
model.addAttribute("fileType", suffix);
|
||||
model.addAttribute("msg", response.getMsg());
|
||||
@@ -49,7 +57,7 @@ public class PdfFilePreviewImpl implements FilePreview {
|
||||
outFilePath = response.getContent();
|
||||
if (ConfigConstants.isCacheEnabled()) {
|
||||
// 加入缓存
|
||||
fileHandlerService.addConvertedFile(pdfName, fileHandlerService.getRelativePath(outFilePath));
|
||||
fileUtils.addConvertedFile(pdfName, fileUtils.getRelativePath(outFilePath));
|
||||
}
|
||||
}
|
||||
List<String> imageUrls = pdfUtils.pdf2jpg(outFilePath, pdfName, baseUrl);
|
||||
@@ -68,17 +76,17 @@ public class PdfFilePreviewImpl implements FilePreview {
|
||||
} else {
|
||||
// 不是http开头,浏览器不能直接访问,需下载到本地
|
||||
if (url != null && !url.toLowerCase().startsWith("http")) {
|
||||
if (!fileHandlerService.listConvertedFiles().containsKey(pdfName) || !ConfigConstants.isCacheEnabled()) {
|
||||
ReturnResponse<String> response = DownloadUtils.downLoad(fileAttribute, pdfName);
|
||||
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", fileHandlerService.getRelativePath(response.getContent()));
|
||||
model.addAttribute("pdfUrl", fileUtils.getRelativePath(response.getContent()));
|
||||
if (ConfigConstants.isCacheEnabled()) {
|
||||
// 加入缓存
|
||||
fileHandlerService.addConvertedFile(pdfName, fileHandlerService.getRelativePath(outFilePath));
|
||||
fileUtils.addConvertedFile(pdfName, fileUtils.getRelativePath(outFilePath));
|
||||
}
|
||||
} else {
|
||||
model.addAttribute("pdfUrl", pdfName);
|
||||
@@ -1,14 +1,16 @@
|
||||
package cn.keking.service.impl;
|
||||
|
||||
import cn.keking.config.ConfigConstants;
|
||||
import cn.keking.model.FileAttribute;
|
||||
import cn.keking.model.ReturnResponse;
|
||||
import cn.keking.service.FilePreview;
|
||||
import cn.keking.utils.DownloadUtils;
|
||||
import cn.keking.service.FileHandlerService;
|
||||
import cn.keking.utils.FileUtils;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import java.util.ArrayList;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -18,33 +20,37 @@ import java.util.List;
|
||||
@Service
|
||||
public class PictureFilePreviewImpl implements FilePreview {
|
||||
|
||||
private final FileHandlerService fileHandlerService;
|
||||
private final FileUtils fileUtils;
|
||||
|
||||
public PictureFilePreviewImpl(FileHandlerService fileHandlerService) {
|
||||
this.fileHandlerService = fileHandlerService;
|
||||
private final DownloadUtils downloadUtils;
|
||||
|
||||
public PictureFilePreviewImpl(FileUtils fileUtils,
|
||||
DownloadUtils downloadUtils) {
|
||||
this.fileUtils = fileUtils;
|
||||
this.downloadUtils = downloadUtils;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
|
||||
List<String> imgUrls = new ArrayList<>();
|
||||
imgUrls.add(url);
|
||||
String fileKey = fileAttribute.getFileKey();
|
||||
List<String> zipImgUrls = fileHandlerService.getImgCache(fileKey);
|
||||
if (!CollectionUtils.isEmpty(zipImgUrls)) {
|
||||
imgUrls.addAll(zipImgUrls);
|
||||
String fileKey = (String) RequestContextHolder.currentRequestAttributes().getAttribute("fileKey",0);
|
||||
List<String> imgUrls = Lists.newArrayList(url);
|
||||
model.addAttribute("switchDisabled", ConfigConstants.getOfficePreviewSwitchDisabled());
|
||||
try {
|
||||
imgUrls.clear();
|
||||
imgUrls.addAll(fileUtils.getImgCache(fileKey));
|
||||
} catch (Exception e){
|
||||
imgUrls = Lists.newArrayList(url);
|
||||
}
|
||||
// 不是http开头,浏览器不能直接访问,需下载到本地
|
||||
if (url != null && !url.toLowerCase().startsWith("http")) {
|
||||
ReturnResponse<String> response = DownloadUtils.downLoad(fileAttribute, null);
|
||||
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 = fileHandlerService.getRelativePath(response.getContent());
|
||||
imgUrls.clear();
|
||||
imgUrls.add(file);
|
||||
model.addAttribute("imgurls", imgUrls);
|
||||
String file = fileUtils.getRelativePath(response.getContent());
|
||||
model.addAttribute("imgurls", Lists.newArrayList(file));
|
||||
model.addAttribute("currentUrl", file);
|
||||
}
|
||||
} else {
|
||||
@@ -4,14 +4,12 @@ import cn.keking.model.FileAttribute;
|
||||
import cn.keking.model.ReturnResponse;
|
||||
import cn.keking.service.FilePreview;
|
||||
import cn.keking.utils.DownloadUtils;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.util.Base64Utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
|
||||
/**
|
||||
* Created by kl on 2018/1/17.
|
||||
@@ -20,30 +18,34 @@ import java.nio.charset.StandardCharsets;
|
||||
@Service
|
||||
public class SimTextFilePreviewImpl implements FilePreview {
|
||||
|
||||
public static final String TEXT_TYPE = "textType";
|
||||
public static final String DEFAULT_TEXT_TYPE = "simText";
|
||||
private final DownloadUtils downloadUtils;
|
||||
|
||||
public SimTextFilePreviewImpl(DownloadUtils downloadUtils) {
|
||||
this.downloadUtils = downloadUtils;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
|
||||
public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute){
|
||||
String fileName = fileAttribute.getName();
|
||||
ReturnResponse<String> response = DownloadUtils.downLoad(fileAttribute, fileName);
|
||||
ReturnResponse<String> response = downloadUtils.downLoad(fileAttribute, fileName);
|
||||
if (0 != response.getCode()) {
|
||||
model.addAttribute("msg", response.getMsg());
|
||||
model.addAttribute("fileType", fileAttribute.getSuffix());
|
||||
model.addAttribute("fileType",fileAttribute.getSuffix());
|
||||
return "fileNotSupported";
|
||||
}
|
||||
try {
|
||||
File originFile = new File(response.getContent());
|
||||
String xmlString = FileUtils.readFileToString(originFile, StandardCharsets.UTF_8);
|
||||
model.addAttribute("textData", Base64Utils.encodeToString(xmlString.getBytes()));
|
||||
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());
|
||||
model.addAttribute("fileType",fileAttribute.getSuffix());
|
||||
return "fileNotSupported";
|
||||
}
|
||||
if (!model.containsAttribute(TEXT_TYPE)) {
|
||||
model.addAttribute(TEXT_TYPE, DEFAULT_TEXT_TYPE);
|
||||
}
|
||||
model.addAttribute("ordinaryUrl", response.getMsg());
|
||||
return "txt";
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package cn.keking.service;
|
||||
package cn.keking.utils;
|
||||
|
||||
import com.sun.star.document.UpdateDocMode;
|
||||
import cn.keking.extend.ControlDocumentFormatRegistry;
|
||||
@@ -9,8 +9,6 @@ import org.artofsolving.jodconverter.office.OfficeManager;
|
||||
import org.artofsolving.jodconverter.office.OfficeUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
@@ -31,23 +29,16 @@ import java.util.Properties;
|
||||
* @date 2017/11/13
|
||||
*/
|
||||
@Component
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
public class OfficePluginManager {
|
||||
public class ConverterUtils {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(OfficePluginManager.class);
|
||||
private final Logger logger = LoggerFactory.getLogger(ConverterUtils.class);
|
||||
|
||||
private OfficeManager officeManager;
|
||||
|
||||
@PostConstruct
|
||||
public void initOfficeManager() {
|
||||
new Thread(this::startOfficeManager).start();
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动Office组件进程
|
||||
*/
|
||||
private void startOfficeManager(){
|
||||
File officeHome = OfficeUtils.getDefaultOfficeHome();
|
||||
File officeHome;
|
||||
officeHome = OfficeUtils.getDefaultOfficeHome();
|
||||
if (officeHome == null) {
|
||||
throw new RuntimeException("找不到office组件,请确认'office.home'配置是否有误");
|
||||
}
|
||||
@@ -1,18 +1,14 @@
|
||||
package cn.keking.utils;
|
||||
|
||||
import cpdetector.CharsetPrinter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
public class FileUtils {
|
||||
public class DeleteFileUtil {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(FileUtils.class);
|
||||
|
||||
public static final String DEFAULT_FILE_ENCODING = "UTF-8";
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DeleteFileUtil.class);
|
||||
|
||||
/**
|
||||
* 删除单个文件
|
||||
@@ -21,7 +17,7 @@ public class FileUtils {
|
||||
* 要删除的文件的文件名
|
||||
* @return 单个文件删除成功返回true,否则返回false
|
||||
*/
|
||||
public static boolean deleteFileByName(String fileName) {
|
||||
public static boolean deleteFile(String fileName) {
|
||||
File file = new File(fileName);
|
||||
// 如果文件路径所对应的文件存在,并且是一个文件,则直接删除
|
||||
if (file.exists() && file.isFile()) {
|
||||
@@ -38,36 +34,6 @@ public class FileUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断文件编码格式
|
||||
*
|
||||
* @param filePath 绝对路径
|
||||
* @return 编码格式
|
||||
*/
|
||||
public static String getFileEncode(String filePath) {
|
||||
File file = new File(filePath);
|
||||
CharsetPrinter cp = new CharsetPrinter();
|
||||
try {
|
||||
String encoding = cp.guessEncoding(file);
|
||||
LOGGER.info("检测到文件【{}】编码: {}", filePath, encoding);
|
||||
return encoding;
|
||||
} catch (IOException e) {
|
||||
LOGGER.warn("文件编码获取失败,采用默认的编码格式:UTF-8", e);
|
||||
return DEFAULT_FILE_ENCODING;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据文件路径删除文件
|
||||
*
|
||||
* @param filePath 绝对路径
|
||||
*/
|
||||
public static void deleteFileByPath(String filePath) {
|
||||
File file = new File(filePath);
|
||||
if (file.exists() && !file.delete()) {
|
||||
LOGGER.warn("压缩包源文件删除失败:{}!", filePath);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除目录及目录下的文件
|
||||
@@ -93,20 +59,20 @@ public class FileUtils {
|
||||
for (int i = 0; i < Objects.requireNonNull(files).length; i++) {
|
||||
// 删除子文件
|
||||
if (files[i].isFile()) {
|
||||
flag = FileUtils.deleteFileByName(files[i].getAbsolutePath());
|
||||
flag = DeleteFileUtil.deleteFile(files[i].getAbsolutePath());
|
||||
if (!flag) {
|
||||
break;
|
||||
}
|
||||
} else if (files[i].isDirectory()) {
|
||||
// 删除子目录
|
||||
flag = FileUtils.deleteDirectory(files[i].getAbsolutePath());
|
||||
flag = DeleteFileUtil.deleteDirectory(files[i].getAbsolutePath());
|
||||
if (!flag) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!dirFile.delete() || !flag) {
|
||||
dirFile.delete();
|
||||
if (!flag) {
|
||||
LOGGER.info("删除目录失败!");
|
||||
return false;
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
package cn.keking.utils;
|
||||
|
||||
import cn.keking.config.ConfigConstants;
|
||||
import cn.keking.hutool.URLUtil;
|
||||
import cn.keking.model.FileAttribute;
|
||||
import cn.keking.model.FileType;
|
||||
import cn.keking.model.ReturnResponse;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
@@ -15,44 +17,53 @@ import java.util.UUID;
|
||||
/**
|
||||
* @author yudian-it
|
||||
*/
|
||||
@Component
|
||||
public class DownloadUtils {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(DownloadUtils.class);
|
||||
private static final String fileDir = ConfigConstants.getFileDir();
|
||||
private final Logger logger = LoggerFactory.getLogger(DownloadUtils.class);
|
||||
|
||||
private final String fileDir = ConfigConstants.getFileDir();
|
||||
|
||||
private final FileUtils fileUtils;
|
||||
|
||||
public DownloadUtils(FileUtils fileUtils) {
|
||||
this.fileUtils = fileUtils;
|
||||
}
|
||||
|
||||
private static final String URL_PARAM_FTP_USERNAME = "ftp.username";
|
||||
private static final String URL_PARAM_FTP_PASSWORD = "ftp.password";
|
||||
private static final String URL_PARAM_FTP_CONTROL_ENCODING = "ftp.control.encoding";
|
||||
|
||||
/**
|
||||
* @param fileAttribute fileAttribute
|
||||
* @param fileName 文件名
|
||||
* @param fileName 文件名
|
||||
* @return 本地文件绝对路径
|
||||
*/
|
||||
public static ReturnResponse<String> downLoad(FileAttribute fileAttribute, String fileName) {
|
||||
public ReturnResponse<String> downLoad(FileAttribute fileAttribute, String fileName) {
|
||||
String urlStr = fileAttribute.getUrl();
|
||||
String type = fileAttribute.getSuffix();
|
||||
ReturnResponse<String> response = new ReturnResponse<>(0, "下载成功!!!", "");
|
||||
UUID uuid = UUID.randomUUID();
|
||||
if (null == fileName) {
|
||||
fileName = uuid + "." + type;
|
||||
fileName = uuid+ "."+type;
|
||||
} else { // 文件后缀不一致时,以type为准(针对simText【将类txt文件转为txt】)
|
||||
fileName = fileName.replace(fileName.substring(fileName.lastIndexOf(".") + 1), type);
|
||||
}
|
||||
String realPath = fileDir + fileName;
|
||||
File dirFile = new File(fileDir);
|
||||
if (!dirFile.exists() && !dirFile.mkdirs()) {
|
||||
logger.error("创建目录【{}】失败,可能是权限不够,请检查", fileDir);
|
||||
if (!dirFile.exists()) {
|
||||
dirFile.mkdirs();
|
||||
}
|
||||
try {
|
||||
URL url = new URL(urlStr);
|
||||
if (url.getProtocol() != null && (url.getProtocol().toLowerCase().startsWith("file") || url.getProtocol().toLowerCase().startsWith("http"))) {
|
||||
if (url.getProtocol() != null && (url.getProtocol().toLowerCase().startsWith("file")||url.getProtocol().toLowerCase().startsWith("http"))) {
|
||||
byte[] bytes = getBytesFromUrl(urlStr);
|
||||
OutputStream os = new FileOutputStream(realPath);
|
||||
saveBytesToOutStream(bytes, os);
|
||||
} else if (url.getProtocol() != null && "ftp".equalsIgnoreCase(url.getProtocol())) {
|
||||
String ftpUsername = WebUtils.getUrlParameterReg(fileAttribute.getUrl(), URL_PARAM_FTP_USERNAME);
|
||||
String ftpPassword = WebUtils.getUrlParameterReg(fileAttribute.getUrl(), URL_PARAM_FTP_PASSWORD);
|
||||
String ftpControlEncoding = WebUtils.getUrlParameterReg(fileAttribute.getUrl(), URL_PARAM_FTP_CONTROL_ENCODING);
|
||||
String ftpUsername = fileUtils.getUrlParameterReg(fileAttribute.getUrl(), URL_PARAM_FTP_USERNAME);
|
||||
String ftpPassword = fileUtils.getUrlParameterReg(fileAttribute.getUrl(), URL_PARAM_FTP_PASSWORD);
|
||||
String ftpControlEncoding = fileUtils.getUrlParameterReg(fileAttribute.getUrl(), URL_PARAM_FTP_CONTROL_ENCODING);
|
||||
FtpUtils.download(fileAttribute.getUrl(), realPath, ftpUsername, ftpPassword, ftpControlEncoding);
|
||||
} else {
|
||||
response.setCode(1);
|
||||
@@ -61,7 +72,7 @@ public class DownloadUtils {
|
||||
}
|
||||
response.setContent(realPath);
|
||||
response.setMsg(fileName);
|
||||
if (FileType.simText.equals(fileAttribute.getType())) {
|
||||
if(FileType.simText.equals(fileAttribute.getType())){
|
||||
convertTextPlainFileCharsetToUtf8(realPath);
|
||||
}
|
||||
return response;
|
||||
@@ -78,25 +89,27 @@ public class DownloadUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] getBytesFromUrl(String urlStr) throws IOException {
|
||||
public byte[] getBytesFromUrl(String urlStr) throws IOException {
|
||||
InputStream is = getInputStreamFromUrl(urlStr);
|
||||
if (is == null) {
|
||||
// urlStr = URLUtil.normalize(urlStr, true, true);
|
||||
if (is != null) {
|
||||
return getBytesFromStream(is);
|
||||
} else {
|
||||
urlStr = URLUtil.normalize(urlStr, true, true);
|
||||
is = getInputStreamFromUrl(urlStr);
|
||||
if (is == null) {
|
||||
logger.error("文件下载异常:url:{}", urlStr);
|
||||
throw new IOException("文件下载异常:url:" + urlStr);
|
||||
}
|
||||
return getBytesFromStream(is);
|
||||
}
|
||||
return getBytesFromStream(is);
|
||||
}
|
||||
|
||||
public static void saveBytesToOutStream(byte[] b, OutputStream os) throws IOException {
|
||||
public void saveBytesToOutStream(byte[] b, OutputStream os) throws IOException {
|
||||
os.write(b);
|
||||
os.close();
|
||||
}
|
||||
|
||||
private static InputStream getInputStreamFromUrl(String urlStr) {
|
||||
private InputStream getInputStreamFromUrl(String urlStr) {
|
||||
try {
|
||||
URL url = new URL(urlStr);
|
||||
URLConnection connection = url.openConnection();
|
||||
@@ -110,10 +123,10 @@ public class DownloadUtils {
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] getBytesFromStream(InputStream is) throws IOException {
|
||||
private byte[] getBytesFromStream(InputStream is) throws IOException {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
byte[] buffer = new byte[1024];
|
||||
int len;
|
||||
int len = 0;
|
||||
while ((len = is.read(buffer)) != -1) {
|
||||
baos.write(buffer, 0, len);
|
||||
}
|
||||
@@ -123,37 +136,41 @@ public class DownloadUtils {
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换文本文件编码为utf8
|
||||
* 探测源文件编码,探测到编码切不为utf8则进行转码
|
||||
*
|
||||
* @param filePath 文件路径
|
||||
*/
|
||||
private static void convertTextPlainFileCharsetToUtf8(String filePath) throws IOException {
|
||||
File sourceFile = new File(filePath);
|
||||
if (sourceFile.exists() && sourceFile.isFile() && sourceFile.canRead()) {
|
||||
String encoding = FileUtils.getFileEncode(filePath);
|
||||
if (!FileUtils.DEFAULT_FILE_ENCODING.equals(encoding)) {
|
||||
// 不为utf8,进行转码
|
||||
File tmpUtf8File = new File(filePath + ".utf8");
|
||||
Writer writer = new OutputStreamWriter(new FileOutputStream(tmpUtf8File), StandardCharsets.UTF_8);
|
||||
Reader reader = new BufferedReader(new InputStreamReader(new FileInputStream(sourceFile), encoding));
|
||||
char[] buf = new char[1024];
|
||||
int read;
|
||||
while ((read = reader.read(buf)) > 0) {
|
||||
writer.write(buf, 0, read);
|
||||
}
|
||||
reader.close();
|
||||
writer.close();
|
||||
// 删除源文件
|
||||
if (!sourceFile.delete()) {
|
||||
logger.error("源文件【{}】删除失败,请检查文件目录权限!", filePath);
|
||||
}
|
||||
// 重命名
|
||||
if (tmpUtf8File.renameTo(sourceFile)) {
|
||||
logger.error("临时文件【{}】重命名失败,请检查文件路径权限!", tmpUtf8File.getPath());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 转换文本文件编码为utf8
|
||||
* 探测源文件编码,探测到编码切不为utf8则进行转码
|
||||
* @param filePath 文件路径
|
||||
*/
|
||||
private static void convertTextPlainFileCharsetToUtf8(String filePath) throws IOException {
|
||||
File sourceFile = new File(filePath);
|
||||
if(sourceFile.exists() && sourceFile.isFile() && sourceFile.canRead()) {
|
||||
String encoding = null;
|
||||
try {
|
||||
FileCharsetDetector.Observer observer = FileCharsetDetector.guessFileEncoding(sourceFile);
|
||||
// 为准确探测到编码,不适用猜测的编码
|
||||
encoding = observer.isFound()?observer.getEncoding():null;
|
||||
// 为准确探测到编码,可以考虑使用GBK 大部分文件都是windows系统产生的
|
||||
} catch (IOException e) {
|
||||
// 编码探测失败,
|
||||
e.printStackTrace();
|
||||
}
|
||||
if(encoding != null && !"UTF-8".equals(encoding)){
|
||||
// 不为utf8,进行转码
|
||||
File tmpUtf8File = new File(filePath+".utf8");
|
||||
Writer writer = new OutputStreamWriter(new FileOutputStream(tmpUtf8File), StandardCharsets.UTF_8);
|
||||
Reader reader = new BufferedReader(new InputStreamReader(new FileInputStream(sourceFile),encoding));
|
||||
char[] buf = new char[1024];
|
||||
int read;
|
||||
while ((read = reader.read(buf)) > 0){
|
||||
writer.write(buf, 0, read);
|
||||
}
|
||||
reader.close();
|
||||
writer.close();
|
||||
// 删除源文件
|
||||
sourceFile.delete();
|
||||
// 重命名
|
||||
tmpUtf8File.renameTo(sourceFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
package cn.keking.utils;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.mozilla.intl.chardet.nsDetector;
|
||||
import org.mozilla.intl.chardet.nsICharsetDetectionObserver;
|
||||
|
||||
/**
|
||||
* 文本文件编码探测工具类
|
||||
*
|
||||
* @author HWliao
|
||||
* @date 2017-12-24
|
||||
*/
|
||||
public class FileCharsetDetector {
|
||||
|
||||
/**
|
||||
* 传入一个文件(File)对象,检查文件编码
|
||||
*
|
||||
* @param file File对象实例
|
||||
* @return 文件编码,若无,则返回null
|
||||
* @throws FileNotFoundException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static Observer guessFileEncoding(File file)
|
||||
throws FileNotFoundException, IOException {
|
||||
return guessFileEncoding(file, new nsDetector());
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 获取文件的编码
|
||||
* @param file
|
||||
* File对象实例
|
||||
* @param languageHint
|
||||
* 语言提示区域代码 @see #nsPSMDetector ,取值如下:
|
||||
* 1 : Japanese
|
||||
* 2 : Chinese
|
||||
* 3 : Simplified Chinese
|
||||
* 4 : Traditional Chinese
|
||||
* 5 : Korean
|
||||
* 6 : Dont know(default)
|
||||
* </pre>
|
||||
*
|
||||
* @return 文件编码,eg:UTF-8,GBK,GB2312形式(不确定的时候,返回可能的字符编码序列);若无,则返回null
|
||||
* @throws FileNotFoundException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static Observer guessFileEncoding(File file, int languageHint)
|
||||
throws FileNotFoundException, IOException {
|
||||
return guessFileEncoding(file, new nsDetector(languageHint));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件的编码
|
||||
*
|
||||
* @param file
|
||||
* @param det
|
||||
* @return
|
||||
* @throws FileNotFoundException
|
||||
* @throws IOException
|
||||
*/
|
||||
private static Observer guessFileEncoding(File file, nsDetector det)
|
||||
throws FileNotFoundException, IOException {
|
||||
// new Observer
|
||||
Observer observer = new Observer();
|
||||
// set Observer
|
||||
// The Notify() will be called when a matching charset is found.
|
||||
det.Init(observer);
|
||||
|
||||
BufferedInputStream imp = new BufferedInputStream(new FileInputStream(
|
||||
file));
|
||||
byte[] buf = new byte[1024];
|
||||
int len;
|
||||
boolean done = false;
|
||||
boolean isAscii = false;
|
||||
|
||||
while ((len = imp.read(buf, 0, buf.length)) != -1) {
|
||||
// Check if the stream is only ascii.
|
||||
isAscii = det.isAscii(buf, len);
|
||||
if (isAscii) {
|
||||
break;
|
||||
}
|
||||
// DoIt if non-ascii and not done yet.
|
||||
done = det.DoIt(buf, len, false);
|
||||
if (done) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
imp.close();
|
||||
det.DataEnd();
|
||||
|
||||
if (isAscii) {
|
||||
observer.encoding = "ASCII";
|
||||
observer.found = true;
|
||||
}
|
||||
|
||||
if (!observer.isFound()) {
|
||||
String[] prob = det.getProbableCharsets();
|
||||
// // 这里将可能的字符集组合起来返回
|
||||
// for (int i = 0; i < prob.length; i++) {
|
||||
// if (i == 0) {
|
||||
// encoding = prob[i];
|
||||
// } else {
|
||||
// encoding += "," + prob[i];
|
||||
// }
|
||||
// }
|
||||
if (prob.length > 0) {
|
||||
// 在没有发现情况下,去第一个可能的编码
|
||||
observer.encoding = prob[0];
|
||||
} else {
|
||||
observer.encoding = null;
|
||||
}
|
||||
}
|
||||
return observer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @author liaohongwei
|
||||
* @Description: 文件字符编码观察者, 但判断出字符编码时候调用
|
||||
* @date 2016年6月20日 下午2:27:06
|
||||
*/
|
||||
public static class Observer implements nsICharsetDetectionObserver {
|
||||
|
||||
/**
|
||||
* @Fields encoding : 字符编码
|
||||
*/
|
||||
private String encoding = null;
|
||||
/**
|
||||
* @Fields found : 是否找到字符集
|
||||
*/
|
||||
private boolean found = false;
|
||||
|
||||
@Override
|
||||
public void Notify(String charset) {
|
||||
this.encoding = charset;
|
||||
this.found = true;
|
||||
}
|
||||
|
||||
public String getEncoding() {
|
||||
return encoding;
|
||||
}
|
||||
|
||||
public boolean isFound() {
|
||||
return found;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Observer [encoding=" + encoding + ", found=" + found + "]";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
339
jodconverter-web/src/main/java/cn/keking/utils/FileUtils.java
Normal file
339
jodconverter-web/src/main/java/cn/keking/utils/FileUtils.java
Normal file
@@ -0,0 +1,339 @@
|
||||
package cn.keking.utils;
|
||||
|
||||
import cn.keking.config.ConfigConstants;
|
||||
import cn.keking.model.FileAttribute;
|
||||
import cn.keking.model.FileType;
|
||||
import cn.keking.service.cache.CacheService;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author yudian-it
|
||||
* @date 2017/11/13
|
||||
*/
|
||||
@Component
|
||||
public class FileUtils {
|
||||
|
||||
private static final String DEFAULT_CONVERTER_CHARSET = System.getProperty("sun.jnu.encoding");
|
||||
|
||||
private final String fileDir = ConfigConstants.getFileDir();
|
||||
private final CacheService cacheService;
|
||||
|
||||
public FileUtils(CacheService cacheService) {
|
||||
this.cacheService = cacheService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 已转换过的文件集合(缓存)
|
||||
*/
|
||||
public Map<String, String> listConvertedFiles() {
|
||||
return cacheService.getPDFCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 已转换过的文件,根据文件名获取
|
||||
*/
|
||||
public String getConvertedFile(String key) {
|
||||
return cacheService.getPDFCache(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key pdf本地路径
|
||||
* @return 已将pdf转换成图片的图片本地相对路径
|
||||
*/
|
||||
public Integer getConvertedPdfImage(String key) {
|
||||
return cacheService.getPdfImageCache(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看文件类型(防止参数中存在.点号或者其他特殊字符,所以先抽取文件名,然后再获取文件类型)
|
||||
*
|
||||
* @param url url
|
||||
* @return 文件类型
|
||||
*/
|
||||
public FileType typeFromUrl(String url) {
|
||||
String nonPramStr = url.substring(0, url.contains("?") ? url.indexOf("?") : url.length());
|
||||
String fileName = nonPramStr.substring(nonPramStr.lastIndexOf("/") + 1);
|
||||
return typeFromFileName(fileName);
|
||||
}
|
||||
|
||||
private FileType typeFromFileName(String fileName) {
|
||||
String[] simText = ConfigConstants.getSimText();
|
||||
String[] media = ConfigConstants.getMedia();
|
||||
String fileType = fileName.substring(fileName.lastIndexOf(".") + 1);
|
||||
if (listPictureTypes().contains(fileType.toLowerCase())) {
|
||||
return FileType.picture;
|
||||
}
|
||||
if (listArchiveTypes().contains(fileType.toLowerCase())) {
|
||||
return FileType.compress;
|
||||
}
|
||||
if (listOfficeTypes().contains(fileType.toLowerCase())) {
|
||||
return FileType.office;
|
||||
}
|
||||
if("md".equalsIgnoreCase(fileType)){
|
||||
return FileType.markdown;
|
||||
}
|
||||
if (Arrays.asList(simText).contains(fileType.toLowerCase())) {
|
||||
return FileType.simText;
|
||||
}
|
||||
if (Arrays.asList(media).contains(fileType.toLowerCase())) {
|
||||
return FileType.media;
|
||||
}
|
||||
if ("pdf".equalsIgnoreCase(fileType)) {
|
||||
return FileType.pdf;
|
||||
}
|
||||
if ("dwg".equalsIgnoreCase(fileType)) {
|
||||
return FileType.cad;
|
||||
}
|
||||
return FileType.other;
|
||||
}
|
||||
/**
|
||||
* 从url中剥离出文件名
|
||||
* @param url
|
||||
* 格式如:http://keking.ufile.ucloud.com.cn/20171113164107_月度绩效表模板(新).xls?UCloudPublicKey=ucloudtangshd@weifenf.com14355492830001993909323&Expires=&Signature=I D1NOFtAJSPT16E6imv6JWuq0k=
|
||||
* @return 文件名
|
||||
*/
|
||||
public String getFileNameFromURL(String url) {
|
||||
// 因为url的参数中可能会存在/的情况,所以直接url.lastIndexOf("/")会有问题
|
||||
// 所以先从?处将url截断,然后运用url.lastIndexOf("/")获取文件名
|
||||
String noQueryUrl = url.substring(0, url.contains("?") ? url.indexOf("?"): url.length());
|
||||
return noQueryUrl.substring(noQueryUrl.lastIndexOf("/") + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从路径中获取文件负
|
||||
* @param path
|
||||
* 类似这种:C:\Users\yudian-it\Downloads
|
||||
* @return 文件名
|
||||
*/
|
||||
public String getFileNameFromPath(String path) {
|
||||
return path.substring(path.lastIndexOf(File.separator) + 1);
|
||||
}
|
||||
|
||||
public List<String> listPictureTypes(){
|
||||
List<String> list = Lists.newArrayList();
|
||||
list.add("jpg");
|
||||
list.add("jpeg");
|
||||
list.add("png");
|
||||
list.add("gif");
|
||||
list.add("bmp");
|
||||
list.add("ico");
|
||||
list.add("RAW");
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<String> listArchiveTypes(){
|
||||
List<String> list = Lists.newArrayList();
|
||||
list.add("rar");
|
||||
list.add("zip");
|
||||
list.add("jar");
|
||||
list.add("7-zip");
|
||||
list.add("tar");
|
||||
list.add("gzip");
|
||||
list.add("7z");
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<String> listOfficeTypes() {
|
||||
List<String> list = Lists.newArrayList();
|
||||
list.add("docx");
|
||||
list.add("doc");
|
||||
list.add("xls");
|
||||
list.add("xlsx");
|
||||
list.add("ppt");
|
||||
list.add("pptx");
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取相对路径
|
||||
* @param absolutePath 绝对路径
|
||||
* @return 相对路径
|
||||
*/
|
||||
public String getRelativePath(String absolutePath) {
|
||||
return absolutePath.substring(fileDir.length());
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加转换后PDF缓存
|
||||
* @param fileName pdf文件名
|
||||
* @param value 缓存相对路径
|
||||
*/
|
||||
public void addConvertedFile(String fileName, String value){
|
||||
cacheService.putPDFCache(fileName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加转换后图片组缓存
|
||||
* @param pdfFilePath pdf文件绝对路径
|
||||
* @param num 图片张数
|
||||
*/
|
||||
public void addConvertedPdfImage(String pdfFilePath, int num){
|
||||
cacheService.putPdfImageCache(pdfFilePath, num);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取redis中压缩包内图片文件
|
||||
* @param fileKey fileKey
|
||||
* @return 图片文件访问url列表
|
||||
*/
|
||||
public List<String> getImgCache(String fileKey){
|
||||
return cacheService.getImgCache(fileKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置redis中压缩包内图片文件
|
||||
* @param fileKey fileKey
|
||||
* @param imgs 图片文件访问url列表
|
||||
*/
|
||||
public void putImgCache(String fileKey,List<String> imgs){
|
||||
cacheService.putImgCache(fileKey, imgs);
|
||||
}
|
||||
/**
|
||||
* 判断文件编码格式
|
||||
* @param path 绝对路径
|
||||
* @return 编码格式
|
||||
*/
|
||||
public String getFileEncodeUTFGBK(String path){
|
||||
String enc = Charset.forName("GBK").name();
|
||||
File file = new File(path);
|
||||
InputStream in;
|
||||
try {
|
||||
in = new FileInputStream(file);
|
||||
byte[] b = new byte[3];
|
||||
in.read(b);
|
||||
in.close();
|
||||
if (b[0] == -17 && b[1] == -69 && b[2] == -65) {
|
||||
enc = StandardCharsets.UTF_8.name();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
System.out.println("文件编码格式为:" + enc);
|
||||
return enc;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对转换后的文件进行操作(改变编码方式)
|
||||
* @param outFilePath 文件绝对路径
|
||||
*/
|
||||
public void doActionConvertedFile(String outFilePath) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
try (InputStream inputStream = new FileInputStream(outFilePath);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, DEFAULT_CONVERTER_CHARSET))){
|
||||
String line;
|
||||
while(null != (line = reader.readLine())){
|
||||
if (line.contains("charset=gb2312")) {
|
||||
line = line.replace("charset=gb2312", "charset=utf-8");
|
||||
}
|
||||
sb.append(line);
|
||||
}
|
||||
// 添加sheet控制头
|
||||
sb.append("<script src=\"js/jquery-3.0.0.min.js\" type=\"text/javascript\"></script>");
|
||||
sb.append("<script src=\"js/excel.header.js\" type=\"text/javascript\"></script>");
|
||||
sb.append("<link rel=\"stylesheet\" href=\"bootstrap/css/bootstrap.min.css\">");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// 重新写入文件
|
||||
try(FileOutputStream fos = new FileOutputStream(outFilePath);
|
||||
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos, StandardCharsets.UTF_8))) {
|
||||
writer.write(sb.toString());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 获取文件后缀
|
||||
* @param url url
|
||||
* @return 文件后缀
|
||||
*/
|
||||
private String suffixFromUrl(String url) {
|
||||
String nonPramStr = url.substring(0, url.contains("?") ? url.indexOf("?") : url.length());
|
||||
String fileName = nonPramStr.substring(nonPramStr.lastIndexOf("/") + 1);
|
||||
return suffixFromFileName(fileName);
|
||||
}
|
||||
|
||||
private String suffixFromFileName(String fileName) {
|
||||
return fileName.substring(fileName.lastIndexOf(".") + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取url中的参数
|
||||
* @param url url
|
||||
* @param name 参数名
|
||||
* @return 参数值
|
||||
*/
|
||||
public String getUrlParameterReg(String url, String name) {
|
||||
Map<String, String> mapRequest = new HashMap<>();
|
||||
String strUrlParam = truncateUrlPage(url);
|
||||
if (strUrlParam == null) {
|
||||
return "";
|
||||
}
|
||||
//每个键值为一组
|
||||
String[] arrSplit = strUrlParam.split("[&]");
|
||||
for(String strSplit : arrSplit) {
|
||||
String[] arrSplitEqual = strSplit.split("[=]");
|
||||
//解析出键值
|
||||
if(arrSplitEqual.length > 1) {
|
||||
//正确解析
|
||||
mapRequest.put(arrSplitEqual[0], arrSplitEqual[1]);
|
||||
} else if (!arrSplitEqual[0].equals("")) {
|
||||
//只有参数没有值,不加入
|
||||
mapRequest.put(arrSplitEqual[0], "");
|
||||
}
|
||||
}
|
||||
return mapRequest.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 去掉url中的路径,留下请求参数部分
|
||||
* @param strURL url地址
|
||||
* @return url请求参数部分
|
||||
*/
|
||||
private String truncateUrlPage(String strURL) {
|
||||
String strAllParam = null;
|
||||
strURL = strURL.trim();
|
||||
String[] arrSplit = strURL.split("[?]");
|
||||
if(strURL.length() > 1) {
|
||||
if(arrSplit.length > 1) {
|
||||
if(arrSplit[1] != null) {
|
||||
strAllParam=arrSplit[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
return strAllParam;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件属性
|
||||
* @param url url
|
||||
* @return 文件属性
|
||||
*/
|
||||
public FileAttribute getFileAttribute(String url) {
|
||||
String fileName;
|
||||
FileType type;
|
||||
String suffix;
|
||||
String fullFileName = getUrlParameterReg(url, "fullfilename");
|
||||
if (StringUtils.hasText(fullFileName)) {
|
||||
fileName = fullFileName;
|
||||
type = typeFromFileName(fileName);
|
||||
suffix = suffixFromFileName(fileName);
|
||||
} else {
|
||||
fileName = getFileNameFromURL(url);
|
||||
type = typeFromUrl(url);
|
||||
suffix = suffixFromUrl(url);
|
||||
}
|
||||
return new FileAttribute(type,suffix,fileName,url);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package cn.keking.service;
|
||||
package cn.keking.utils;
|
||||
|
||||
import org.artofsolving.jodconverter.OfficeDocumentConverter;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -9,11 +9,11 @@ import java.io.File;
|
||||
* @author yudian-it
|
||||
*/
|
||||
@Component
|
||||
public class OfficeToPdfService {
|
||||
private final OfficePluginManager officePluginManager;
|
||||
public class OfficeToPdf {
|
||||
private final ConverterUtils converterUtils;
|
||||
|
||||
public OfficeToPdfService(OfficePluginManager officePluginManager) {
|
||||
this.officePluginManager = officePluginManager;
|
||||
public OfficeToPdf(ConverterUtils converterUtils) {
|
||||
this.converterUtils = converterUtils;
|
||||
}
|
||||
|
||||
public void openOfficeToPDF(String inputFilePath, String outputFilePath) {
|
||||
@@ -33,7 +33,7 @@ public class OfficeToPdfService {
|
||||
|
||||
|
||||
public void office2pdf(String inputFilePath, String outputFilePath) {
|
||||
OfficeDocumentConverter converter = officePluginManager.getDocumentConverter();
|
||||
OfficeDocumentConverter converter = converterUtils.getDocumentConverter();
|
||||
if (null != inputFilePath) {
|
||||
File inputFile = new File(inputFilePath);
|
||||
// 判断目标文件路径是否为空
|
||||
@@ -1,6 +1,5 @@
|
||||
package cn.keking.utils;
|
||||
|
||||
import cn.keking.service.FileHandlerService;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.rendering.ImageType;
|
||||
import org.apache.pdfbox.rendering.PDFRenderer;
|
||||
@@ -23,18 +22,18 @@ public class PdfUtils {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(PdfUtils.class);
|
||||
|
||||
private final FileHandlerService fileHandlerService;
|
||||
private final FileUtils fileUtils;
|
||||
|
||||
@Value("${server.tomcat.uri-encoding:UTF-8}")
|
||||
private String uriEncoding;
|
||||
|
||||
public PdfUtils(FileHandlerService fileHandlerService) {
|
||||
this.fileHandlerService = fileHandlerService;
|
||||
public PdfUtils(FileUtils fileUtils) {
|
||||
this.fileUtils = fileUtils;
|
||||
}
|
||||
|
||||
public List<String> pdf2jpg(String pdfFilePath, String pdfName, String baseUrl) {
|
||||
List<String> imageUrls = new ArrayList<>();
|
||||
Integer imageCount = fileHandlerService.getConvertedPdfImage(pdfFilePath);
|
||||
Integer imageCount = fileUtils.getConvertedPdfImage(pdfFilePath);
|
||||
String imageFileSuffix = ".jpg";
|
||||
String pdfFolder = pdfName.substring(0, pdfName.length() - 4);
|
||||
String urlPrefix = null;
|
||||
@@ -70,7 +69,7 @@ public class PdfUtils {
|
||||
imageUrls.add(urlPrefix + "/" + pageIndex + imageFileSuffix);
|
||||
}
|
||||
doc.close();
|
||||
fileHandlerService.addConvertedPdfImage(pdfFilePath, pageCount);
|
||||
fileUtils.addConvertedPdfImage(pdfFilePath, pageCount);
|
||||
} catch (IOException e) {
|
||||
logger.error("Convert pdf to jpg exception, pdfFilePath:{}", pdfFilePath, e);
|
||||
}
|
||||
@@ -31,7 +31,7 @@ public class ShedulerClean {
|
||||
public void clean() {
|
||||
logger.info("Cache clean start");
|
||||
cacheService.cleanCache();
|
||||
FileUtils.deleteDirectory(fileDir);
|
||||
DeleteFileUtil.deleteDirectory(fileDir);
|
||||
logger.info("Cache clean end");
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,15 @@
|
||||
package cn.keking.service;
|
||||
package cn.keking.utils;
|
||||
|
||||
import cn.keking.config.ConfigConstants;
|
||||
import cn.keking.model.FileType;
|
||||
import cn.keking.utils.FileUtils;
|
||||
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 com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.sevenz.SevenZFile;
|
||||
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
|
||||
@@ -26,34 +27,37 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author yudian-it
|
||||
* create 2017/11/27
|
||||
* @date 2017/11/27
|
||||
*/
|
||||
@Component
|
||||
public class CompressFileReader {
|
||||
public class ZipReader {
|
||||
static Pattern pattern = Pattern.compile("^\\d+");
|
||||
|
||||
private final FileUtils fileUtils;
|
||||
|
||||
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 ZipReader(FileUtils fileUtils) {
|
||||
this.fileUtils = fileUtils;
|
||||
}
|
||||
|
||||
public String readZipFile(String filePath, String fileKey) {
|
||||
public String readZipFile(String filePath,String fileKey) {
|
||||
String archiveSeparator = "/";
|
||||
Map<String, FileNode> appender = new HashMap<>();
|
||||
List<String> imgUrls = new LinkedList<>();
|
||||
Map<String, FileNode> appender = Maps.newHashMap();
|
||||
List<String> imgUrls = Lists.newArrayList();
|
||||
String baseUrl = BaseUrlFilter.getBaseUrl();
|
||||
String archiveFileName = fileHandlerService.getFileNameFromPath(filePath);
|
||||
String archiveFileName = fileUtils.getFileNameFromPath(filePath);
|
||||
try {
|
||||
ZipFile zipFile = new ZipFile(filePath, FileUtils.getFileEncode(filePath));
|
||||
ZipFile zipFile = new ZipFile(filePath, fileUtils.getFileEncodeUTFGBK(filePath));
|
||||
Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
|
||||
// 排序
|
||||
entries = sortZipEntries(entries);
|
||||
List<Map<String, ZipArchiveEntry>> entriesToBeExtracted = new LinkedList<>();
|
||||
while (entries.hasMoreElements()) {
|
||||
List<Map<String, ZipArchiveEntry>> entriesToBeExtracted = Lists.newArrayList();
|
||||
while (entries.hasMoreElements()){
|
||||
ZipArchiveEntry entry = entries.nextElement();
|
||||
String fullName = entry.getName();
|
||||
int level = fullName.split(archiveSeparator).length;
|
||||
@@ -66,10 +70,10 @@ public class CompressFileReader {
|
||||
entriesToBeExtracted.add(Collections.singletonMap(childName, entry));
|
||||
}
|
||||
String parentName = getLast2FileName(fullName, archiveSeparator, archiveFileName);
|
||||
parentName = (level - 1) + "_" + parentName;
|
||||
FileType type = fileHandlerService.typeFromUrl(childName);
|
||||
if (type.equals(FileType.picture)) {//添加图片文件到图片列表
|
||||
imgUrls.add(baseUrl + childName);
|
||||
parentName = (level-1) + "_" + parentName;
|
||||
FileType type=fileUtils.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);
|
||||
@@ -77,7 +81,7 @@ public class CompressFileReader {
|
||||
}
|
||||
// 开启新的线程处理文件解压
|
||||
executors.submit(new ZipExtractorWorker(entriesToBeExtracted, zipFile, filePath));
|
||||
fileHandlerService.putImgCache(fileKey, imgUrls);
|
||||
fileUtils.putImgCache(fileKey,imgUrls);
|
||||
return new ObjectMapper().writeValueAsString(appender.get(""));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
@@ -86,29 +90,29 @@ public class CompressFileReader {
|
||||
}
|
||||
|
||||
private Enumeration<ZipArchiveEntry> sortZipEntries(Enumeration<ZipArchiveEntry> entries) {
|
||||
List<ZipArchiveEntry> sortedEntries = new LinkedList<>();
|
||||
while (entries.hasMoreElements()) {
|
||||
List<ZipArchiveEntry> sortedEntries = Lists.newArrayList();
|
||||
while(entries.hasMoreElements()){
|
||||
sortedEntries.add(entries.nextElement());
|
||||
}
|
||||
sortedEntries.sort(Comparator.comparingInt(o -> o.getName().length()));
|
||||
return Collections.enumeration(sortedEntries);
|
||||
}
|
||||
|
||||
public String unRar(String filePath, String fileKey) {
|
||||
Map<String, FileNode> appender = new HashMap<>();
|
||||
List<String> imgUrls = new ArrayList<>();
|
||||
public String unRar(String filePath,String fileKey){
|
||||
Map<String, FileNode> appender = Maps.newHashMap();
|
||||
List<String> imgUrls = Lists.newArrayList();
|
||||
String baseUrl = BaseUrlFilter.getBaseUrl();
|
||||
try {
|
||||
Archive archive = new Archive(new FileInputStream(filePath));
|
||||
Archive archive = new Archive(new FileInputStream(new File(filePath)));
|
||||
List<FileHeader> headers = archive.getFileHeaders();
|
||||
headers = sortedHeaders(headers);
|
||||
String archiveFileName = fileHandlerService.getFileNameFromPath(filePath);
|
||||
List<Map<String, FileHeader>> headersToBeExtracted = new ArrayList<>();
|
||||
String archiveFileName = fileUtils.getFileNameFromPath(filePath);
|
||||
List<Map<String, FileHeader>> headersToBeExtracted = Lists.newArrayList();
|
||||
for (FileHeader header : headers) {
|
||||
String fullName;
|
||||
if (header.isUnicode()) {
|
||||
fullName = header.getFileNameW();
|
||||
} else {
|
||||
}else {
|
||||
fullName = header.getFileNameString();
|
||||
}
|
||||
// 展示名
|
||||
@@ -120,16 +124,16 @@ public class CompressFileReader {
|
||||
headersToBeExtracted.add(Collections.singletonMap(childName, header));
|
||||
}
|
||||
String parentName = getLast2FileName(fullName, "\\", archiveFileName);
|
||||
FileType type = fileHandlerService.typeFromUrl(childName);
|
||||
if (type.equals(FileType.picture)) {//添加图片文件到图片列表
|
||||
imgUrls.add(baseUrl + childName);
|
||||
FileType type = fileUtils.typeFromUrl(childName);
|
||||
if (type.equals(FileType.picture)){//添加图片文件到图片列表
|
||||
imgUrls.add(baseUrl+childName);
|
||||
}
|
||||
FileNode node = new FileNode(originName, childName, parentName, new ArrayList<>(), directory, fileKey);
|
||||
addNodes(appender, parentName, node);
|
||||
appender.put(childName, node);
|
||||
}
|
||||
executors.submit(new RarExtractorWorker(headersToBeExtracted, archive, filePath));
|
||||
fileHandlerService.putImgCache(fileKey, imgUrls);
|
||||
fileUtils.putImgCache(fileKey,imgUrls);
|
||||
return new ObjectMapper().writeValueAsString(appender.get(""));
|
||||
} catch (RarException | IOException e) {
|
||||
e.printStackTrace();
|
||||
@@ -137,19 +141,19 @@ public class CompressFileReader {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String read7zFile(String filePath, String fileKey) {
|
||||
public String read7zFile(String filePath,String fileKey) {
|
||||
String archiveSeparator = "/";
|
||||
Map<String, FileNode> appender = new HashMap<>();
|
||||
List<String> imgUrls = new ArrayList<>();
|
||||
String baseUrl = BaseUrlFilter.getBaseUrl();
|
||||
String archiveFileName = fileHandlerService.getFileNameFromPath(filePath);
|
||||
Map<String, FileNode> appender = Maps.newHashMap();
|
||||
List<String> imgUrls = Lists.newArrayList();
|
||||
String baseUrl= BaseUrlFilter.getBaseUrl();
|
||||
String archiveFileName = fileUtils.getFileNameFromPath(filePath);
|
||||
try {
|
||||
SevenZFile zipFile = new SevenZFile(new File(filePath));
|
||||
Iterable<SevenZArchiveEntry> entries = zipFile.getEntries();
|
||||
// 排序
|
||||
Enumeration<SevenZArchiveEntry> newEntries = sortSevenZEntries(entries);
|
||||
List<Map<String, SevenZArchiveEntry>> entriesToBeExtracted = new ArrayList<>();
|
||||
while (newEntries.hasMoreElements()) {
|
||||
List<Map<String, SevenZArchiveEntry>> entriesToBeExtracted = Lists.newArrayList();
|
||||
while (newEntries.hasMoreElements()){
|
||||
SevenZArchiveEntry entry = newEntries.nextElement();
|
||||
String fullName = entry.getName();
|
||||
int level = fullName.split(archiveSeparator).length;
|
||||
@@ -162,10 +166,10 @@ public class CompressFileReader {
|
||||
entriesToBeExtracted.add(Collections.singletonMap(childName, entry));
|
||||
}
|
||||
String parentName = getLast2FileName(fullName, archiveSeparator, archiveFileName);
|
||||
parentName = (level - 1) + "_" + parentName;
|
||||
FileType type = fileHandlerService.typeFromUrl(childName);
|
||||
if (type.equals(FileType.picture)) {//添加图片文件到图片列表
|
||||
imgUrls.add(baseUrl + childName);
|
||||
parentName = (level-1) + "_" + parentName;
|
||||
FileType type=fileUtils.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);
|
||||
@@ -173,7 +177,7 @@ public class CompressFileReader {
|
||||
}
|
||||
// 开启新的线程处理文件解压
|
||||
executors.submit(new SevenZExtractorWorker(entriesToBeExtracted, filePath));
|
||||
fileHandlerService.putImgCache(fileKey, imgUrls);
|
||||
fileUtils.putImgCache(fileKey,imgUrls);
|
||||
return new ObjectMapper().writeValueAsString(appender.get(""));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
@@ -183,7 +187,7 @@ public class CompressFileReader {
|
||||
|
||||
|
||||
private Enumeration<SevenZArchiveEntry> sortSevenZEntries(Iterable<SevenZArchiveEntry> entries) {
|
||||
List<SevenZArchiveEntry> sortedEntries = new ArrayList<>();
|
||||
List<SevenZArchiveEntry> sortedEntries = Lists.newArrayList();
|
||||
for (SevenZArchiveEntry entry : entries) {
|
||||
sortedEntries.add(entry);
|
||||
}
|
||||
@@ -207,7 +211,7 @@ public class CompressFileReader {
|
||||
List<FileHeader> sortedHeaders = new ArrayList<>();
|
||||
Map<Integer, FileHeader> mapHeaders = new TreeMap<>();
|
||||
headers.forEach(header -> mapHeaders.put(new Integer(0).equals(header.getFileNameW().length()) ? header.getFileNameString().length() : header.getFileNameW().length(), header));
|
||||
for (Map.Entry<Integer, FileHeader> entry : mapHeaders.entrySet()) {
|
||||
for (Map.Entry<Integer, FileHeader> entry : mapHeaders.entrySet()){
|
||||
for (FileHeader header : headers) {
|
||||
if (entry.getKey().equals(new Integer(0).equals(header.getFileNameW().length()) ? header.getFileNameString().length() : header.getFileNameW().length())) {
|
||||
sortedHeaders.add(header);
|
||||
@@ -219,7 +223,7 @@ public class CompressFileReader {
|
||||
|
||||
private static String getLast2FileName(String fullName, String seperator, String rootName) {
|
||||
if (fullName.endsWith(seperator)) {
|
||||
fullName = fullName.substring(0, fullName.length() - 1);
|
||||
fullName = fullName.substring(0, fullName.length()-1);
|
||||
}
|
||||
// 1.获取剩余部分
|
||||
int endIndex = fullName.lastIndexOf(seperator);
|
||||
@@ -234,7 +238,7 @@ public class CompressFileReader {
|
||||
|
||||
private static String getLastFileName(String fullName, String seperator) {
|
||||
if (fullName.endsWith(seperator)) {
|
||||
fullName = fullName.substring(0, fullName.length() - 1);
|
||||
fullName = fullName.substring(0, fullName.length()-1);
|
||||
}
|
||||
String newName = fullName;
|
||||
if (fullName.contains(seperator)) {
|
||||
@@ -245,11 +249,10 @@ public class CompressFileReader {
|
||||
|
||||
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;
|
||||
BigDecimal num1,num2;
|
||||
if (null != (num1 = isStartNumber(o1))
|
||||
&& null != (num2 = isStartNumber(o2))) {
|
||||
return num1.subtract(num2).intValue();
|
||||
@@ -285,16 +288,14 @@ public class CompressFileReader {
|
||||
this.childList = childList;
|
||||
this.directory = directory;
|
||||
}
|
||||
|
||||
public FileNode(String originName, String fileName, String parentFileName, List<FileNode> childList, boolean directory, String fileKey) {
|
||||
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;
|
||||
this.fileKey=fileKey;
|
||||
}
|
||||
|
||||
public String getFileKey() {
|
||||
return fileKey;
|
||||
}
|
||||
@@ -382,15 +383,17 @@ public class CompressFileReader {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
FileUtils.deleteFileByPath(filePath);
|
||||
if (new File(filePath).exists()) {
|
||||
new File(filePath).delete();
|
||||
}
|
||||
}
|
||||
|
||||
private void extractZipFile(String childName, InputStream zipFile) {
|
||||
String outPath = fileDir + childName;
|
||||
try (OutputStream ot = new FileOutputStream(outPath)) {
|
||||
try (OutputStream ot = new FileOutputStream(outPath)){
|
||||
byte[] inByte = new byte[1024];
|
||||
int len;
|
||||
while ((-1 != (len = zipFile.read(inByte)))) {
|
||||
while ((-1 != (len = zipFile.read(inByte)))){
|
||||
ot.write(inByte, 0, len);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
@@ -439,7 +442,10 @@ public class CompressFileReader {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
FileUtils.deleteFileByPath(filePath);
|
||||
|
||||
if (new File(filePath).exists()) {
|
||||
new File(filePath).delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -468,12 +474,14 @@ public class CompressFileReader {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
FileUtils.deleteFileByPath(filePath);
|
||||
if (new File(filePath).exists()) {
|
||||
new File(filePath).delete();
|
||||
}
|
||||
}
|
||||
|
||||
private void extractRarFile(String childName, FileHeader header, Archive archive) {
|
||||
String outPath = fileDir + childName;
|
||||
try (OutputStream ot = new FileOutputStream(outPath)) {
|
||||
try(OutputStream ot = new FileOutputStream(outPath)) {
|
||||
archive.extractFile(header, ot);
|
||||
} catch (IOException | RarException e) {
|
||||
e.printStackTrace();
|
||||
@@ -3,7 +3,8 @@ package cn.keking.web.controller;
|
||||
import cn.keking.config.ConfigConstants;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Lists;
|
||||
import cn.keking.model.ReturnResponse;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -15,7 +16,10 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -52,8 +56,8 @@ public class FileController {
|
||||
return new ObjectMapper().writeValueAsString(new ReturnResponse<String>(1, "存在同名文件,请先删除原有文件再次上传", null));
|
||||
}
|
||||
File outFile = new File(fileDir + demoPath);
|
||||
if (!outFile.exists() && !outFile.mkdirs()) {
|
||||
logger.error("创建文件夹【{}】失败,请检查目录权限!",fileDir + demoPath);
|
||||
if (!outFile.exists()) {
|
||||
outFile.mkdirs();
|
||||
}
|
||||
logger.info("上传文件:{}", fileDir + demoPath + fileName);
|
||||
try(InputStream in = file.getInputStream(); OutputStream out = new FileOutputStream(fileDir + demoPath + fileName)) {
|
||||
@@ -72,22 +76,18 @@ public class FileController {
|
||||
}
|
||||
File file = new File(fileDir + demoPath + fileName);
|
||||
logger.info("删除文件:{}", file.getAbsolutePath());
|
||||
if (file.exists() && !file.delete()) {
|
||||
logger.error("删除文件【{}】失败,请检查目录权限!",file.getPath());
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
}
|
||||
return new ObjectMapper().writeValueAsString(new ReturnResponse<String>(0, "SUCCESS", null));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "listFiles", method = RequestMethod.GET)
|
||||
public String getFiles() throws JsonProcessingException {
|
||||
List<Map<String, String>> list = new ArrayList<>();
|
||||
List<Map<String, String>> list = Lists.newArrayList();
|
||||
File file = new File(fileDir + demoPath);
|
||||
if (file.exists()) {
|
||||
Arrays.stream(Objects.requireNonNull(file.listFiles())).forEach(file1 -> {
|
||||
Map<String, String> fileName = new HashMap<>();
|
||||
fileName.put("fileName", demoDir + "/" + file1.getName());
|
||||
list.add(fileName);
|
||||
});
|
||||
Arrays.stream(Objects.requireNonNull(file.listFiles())).forEach(file1 -> list.add(ImmutableMap.of("fileName", demoDir + "/" + file1.getName())));
|
||||
}
|
||||
return new ObjectMapper().writeValueAsString(list);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user