diff --git a/itools-core/itools-common/pom.xml b/itools-core/itools-common/pom.xml
index cf83904e1f1f275704c62f3f2c6f2ce44ad72b4c..9f9b8ec917328bd0db2aa73d0019d075da4b1cc3 100644
--- a/itools-core/itools-common/pom.xml
+++ b/itools-core/itools-common/pom.xml
@@ -57,10 +57,20 @@
org.projectlombok
lombok
+
io.springfox
springfox-swagger2
+
+ io.springfox
+ springfox-swagger-ui
+
+
+ com.github.xiaoymin
+ swagger-bootstrap-ui
+ 1.9.6
+
com.google.guava
guava
diff --git a/itools-core/itools-common/src/main/java/com/itools/core/config/Swagger2Config.java b/itools-core/itools-common/src/main/java/com/itools/core/config/Swagger2Config.java
index a74eefb01d11aff07c537dd1cfee157d5a90739c..f0b05cc776a731666e9840c82f5448a8c10e7ab8 100644
--- a/itools-core/itools-common/src/main/java/com/itools/core/config/Swagger2Config.java
+++ b/itools-core/itools-common/src/main/java/com/itools/core/config/Swagger2Config.java
@@ -1,5 +1,6 @@
package com.itools.core.config;
+import io.swagger.annotations.ApiOperation;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
@@ -19,8 +20,9 @@ public class Swagger2Config {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
- .apis(RequestHandlerSelectors.basePackage("com.xuchang.itools"))
- .paths(PathSelectors.any())
+// .apis(RequestHandlerSelectors.basePackage("com.xuchang.itools"))
+// .paths(PathSelectors.any())
+ .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.build();
}
diff --git a/itools-core/itools-common/src/main/java/com/itools/core/validate/EnableValidator.java b/itools-core/itools-common/src/main/java/com/itools/core/validate/EnableValidator.java
index cb426ad4888938799bf39be446e55221b32c8a46..fa6a9b1070480dfd5fe7e6191705b3528c473239 100644
--- a/itools-core/itools-common/src/main/java/com/itools/core/validate/EnableValidator.java
+++ b/itools-core/itools-common/src/main/java/com/itools/core/validate/EnableValidator.java
@@ -5,6 +5,9 @@ import org.springframework.context.annotation.Import;
import java.lang.annotation.*;
+/**
+ * @author xuchang
+ */
@Target(ElementType.TYPE)
@Documented
@Retention(RetentionPolicy.RUNTIME)
diff --git a/itools-core/itools-utils/src/main/java/com/itools/core/utils/Base64.java b/itools-core/itools-utils/src/main/java/com/itools/core/utils/Base64.java
new file mode 100644
index 0000000000000000000000000000000000000000..1fbfccb24d59c87aac21c9570019514b3fce0b62
--- /dev/null
+++ b/itools-core/itools-utils/src/main/java/com/itools/core/utils/Base64.java
@@ -0,0 +1,224 @@
+package com.itools.core.utils;
+
+public class Base64 {
+ private static final byte[] encodingTable = new byte[]{65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47};
+ private static final byte[] decodingTable = new byte[128];
+
+ public Base64() {
+ }
+
+ public static byte[] encode(byte[] data) {
+ int modulus = data.length % 3;
+ byte[] bytes;
+ if (modulus == 0) {
+ bytes = new byte[4 * data.length / 3];
+ } else {
+ bytes = new byte[4 * (data.length / 3 + 1)];
+ }
+
+ int dataLength = data.length - modulus;
+ int b1 = 0;
+
+ int b2;
+ for(b2 = 0; b1 < dataLength; b2 += 4) {
+ int a1 = data[b1] & 255;
+ int a2 = data[b1 + 1] & 255;
+ int a3 = data[b1 + 2] & 255;
+ bytes[b2] = encodingTable[a1 >>> 2 & 63];
+ bytes[b2 + 1] = encodingTable[(a1 << 4 | a2 >>> 4) & 63];
+ bytes[b2 + 2] = encodingTable[(a2 << 2 | a3 >>> 6) & 63];
+ bytes[b2 + 3] = encodingTable[a3 & 63];
+ b1 += 3;
+ }
+
+ int d1;
+ switch(modulus) {
+ case 0:
+ default:
+ break;
+ case 1:
+ d1 = data[data.length - 1] & 255;
+ b1 = d1 >>> 2 & 63;
+ b2 = d1 << 4 & 63;
+ bytes[bytes.length - 4] = encodingTable[b1];
+ bytes[bytes.length - 3] = encodingTable[b2];
+ bytes[bytes.length - 2] = 61;
+ bytes[bytes.length - 1] = 61;
+ break;
+ case 2:
+ d1 = data[data.length - 2] & 255;
+ int d2 = data[data.length - 1] & 255;
+ b1 = d1 >>> 2 & 63;
+ b2 = (d1 << 4 | d2 >>> 4) & 63;
+ int b3 = d2 << 2 & 63;
+ bytes[bytes.length - 4] = encodingTable[b1];
+ bytes[bytes.length - 3] = encodingTable[b2];
+ bytes[bytes.length - 2] = encodingTable[b3];
+ bytes[bytes.length - 1] = 61;
+ }
+
+ return bytes;
+ }
+
+ public static byte[] decode(byte[] data) {
+ data = discardNonBase64Bytes(data);
+ byte[] bytes;
+ if (data[data.length - 2] == 61) {
+ bytes = new byte[(data.length / 4 - 1) * 3 + 1];
+ } else if (data[data.length - 1] == 61) {
+ bytes = new byte[(data.length / 4 - 1) * 3 + 2];
+ } else {
+ bytes = new byte[data.length / 4 * 3];
+ }
+
+ int i = 0;
+
+ byte b1;
+ byte b2;
+ byte b3;
+ byte b4;
+ for(int j = 0; i < data.length - 4; j += 3) {
+ b1 = decodingTable[data[i]];
+ b2 = decodingTable[data[i + 1]];
+ b3 = decodingTable[data[i + 2]];
+ b4 = decodingTable[data[i + 3]];
+ bytes[j] = (byte)(b1 << 2 | b2 >> 4);
+ bytes[j + 1] = (byte)(b2 << 4 | b3 >> 2);
+ bytes[j + 2] = (byte)(b3 << 6 | b4);
+ i += 4;
+ }
+
+ if (data[data.length - 2] == 61) {
+ b1 = decodingTable[data[data.length - 4]];
+ b2 = decodingTable[data[data.length - 3]];
+ bytes[bytes.length - 1] = (byte)(b1 << 2 | b2 >> 4);
+ } else if (data[data.length - 1] == 61) {
+ b1 = decodingTable[data[data.length - 4]];
+ b2 = decodingTable[data[data.length - 3]];
+ b3 = decodingTable[data[data.length - 2]];
+ bytes[bytes.length - 2] = (byte)(b1 << 2 | b2 >> 4);
+ bytes[bytes.length - 1] = (byte)(b2 << 4 | b3 >> 2);
+ } else {
+ b1 = decodingTable[data[data.length - 4]];
+ b2 = decodingTable[data[data.length - 3]];
+ b3 = decodingTable[data[data.length - 2]];
+ b4 = decodingTable[data[data.length - 1]];
+ bytes[bytes.length - 3] = (byte)(b1 << 2 | b2 >> 4);
+ bytes[bytes.length - 2] = (byte)(b2 << 4 | b3 >> 2);
+ bytes[bytes.length - 1] = (byte)(b3 << 6 | b4);
+ }
+
+ return bytes;
+ }
+
+ public static byte[] decode(String data) {
+ data = discardNonBase64Chars(data);
+ byte[] bytes;
+ if (data.charAt(data.length() - 2) == '=') {
+ bytes = new byte[(data.length() / 4 - 1) * 3 + 1];
+ } else if (data.charAt(data.length() - 1) == '=') {
+ bytes = new byte[(data.length() / 4 - 1) * 3 + 2];
+ } else {
+ bytes = new byte[data.length() / 4 * 3];
+ }
+
+ int i = 0;
+
+ byte b1;
+ byte b2;
+ byte b3;
+ byte b4;
+ for(int j = 0; i < data.length() - 4; j += 3) {
+ b1 = decodingTable[data.charAt(i)];
+ b2 = decodingTable[data.charAt(i + 1)];
+ b3 = decodingTable[data.charAt(i + 2)];
+ b4 = decodingTable[data.charAt(i + 3)];
+ bytes[j] = (byte)(b1 << 2 | b2 >> 4);
+ bytes[j + 1] = (byte)(b2 << 4 | b3 >> 2);
+ bytes[j + 2] = (byte)(b3 << 6 | b4);
+ i += 4;
+ }
+
+ if (data.charAt(data.length() - 2) == '=') {
+ b1 = decodingTable[data.charAt(data.length() - 4)];
+ b2 = decodingTable[data.charAt(data.length() - 3)];
+ bytes[bytes.length - 1] = (byte)(b1 << 2 | b2 >> 4);
+ } else if (data.charAt(data.length() - 1) == '=') {
+ b1 = decodingTable[data.charAt(data.length() - 4)];
+ b2 = decodingTable[data.charAt(data.length() - 3)];
+ b3 = decodingTable[data.charAt(data.length() - 2)];
+ bytes[bytes.length - 2] = (byte)(b1 << 2 | b2 >> 4);
+ bytes[bytes.length - 1] = (byte)(b2 << 4 | b3 >> 2);
+ } else {
+ b1 = decodingTable[data.charAt(data.length() - 4)];
+ b2 = decodingTable[data.charAt(data.length() - 3)];
+ b3 = decodingTable[data.charAt(data.length() - 2)];
+ b4 = decodingTable[data.charAt(data.length() - 1)];
+ bytes[bytes.length - 3] = (byte)(b1 << 2 | b2 >> 4);
+ bytes[bytes.length - 2] = (byte)(b2 << 4 | b3 >> 2);
+ bytes[bytes.length - 1] = (byte)(b3 << 6 | b4);
+ }
+
+ return bytes;
+ }
+
+ private static byte[] discardNonBase64Bytes(byte[] data) {
+ byte[] temp = new byte[data.length];
+ int bytesCopied = 0;
+
+ for(int i = 0; i < data.length; ++i) {
+ if (isValidBase64Byte(data[i])) {
+ temp[bytesCopied++] = data[i];
+ }
+ }
+
+ byte[] newData = new byte[bytesCopied];
+ System.arraycopy(temp, 0, newData, 0, bytesCopied);
+ return newData;
+ }
+
+ private static String discardNonBase64Chars(String data) {
+ StringBuffer sb = new StringBuffer();
+ int length = data.length();
+
+ for(int i = 0; i < length; ++i) {
+ if (isValidBase64Byte((byte)data.charAt(i))) {
+ sb.append(data.charAt(i));
+ }
+ }
+
+ return sb.toString();
+ }
+
+ private static boolean isValidBase64Byte(byte b) {
+ if (b == 61) {
+ return true;
+ } else if (b >= 0 && b < 128) {
+ return decodingTable[b] != -1;
+ } else {
+ return false;
+ }
+ }
+
+ static {
+ int i;
+ for(i = 0; i < 128; ++i) {
+ decodingTable[i] = -1;
+ }
+
+ for(i = 65; i <= 90; ++i) {
+ decodingTable[i] = (byte)(i - 65);
+ }
+
+ for(i = 97; i <= 122; ++i) {
+ decodingTable[i] = (byte)(i - 97 + 26);
+ }
+
+ for(i = 48; i <= 57; ++i) {
+ decodingTable[i] = (byte)(i - 48 + 52);
+ }
+
+ decodingTable[43] = 62;
+ decodingTable[47] = 63;
+ }
+}
\ No newline at end of file
diff --git a/itools-core/itools-utils/src/main/java/com/itools/core/utils/Base64Utils.java b/itools-core/itools-utils/src/main/java/com/itools/core/utils/Base64Utils.java
new file mode 100644
index 0000000000000000000000000000000000000000..c033222e1687b569c8dea3c0b3925767536f2157
--- /dev/null
+++ b/itools-core/itools-utils/src/main/java/com/itools/core/utils/Base64Utils.java
@@ -0,0 +1,80 @@
+package com.itools.core.utils;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class Base64Utils {
+ private static final int CACHE_SIZE = 1024;
+
+ public Base64Utils() {
+ }
+
+ public static byte[] decode(String base64) {
+ return Base64.decode(base64.getBytes());
+ }
+
+ public static String encode(byte[] bytes) {
+ return new String(Base64.encode(bytes));
+ }
+
+ public static String encodeFile(String filePath) throws IOException {
+ byte[] bytes = fileToByte(filePath);
+ return encode(bytes);
+ }
+
+ public static void decodeToFile(String filePath, String base64) throws IOException {
+ byte[] bytes = decode(base64);
+ byteArrayToFile(bytes, filePath);
+ }
+
+ public static byte[] fileToByte(String filePath) throws IOException {
+ byte[] data = new byte[0];
+ File file = new File(filePath);
+ if (file.exists()) {
+ FileInputStream in = new FileInputStream(file);
+ ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
+ byte[] cache = new byte[1024];
+ boolean var6 = false;
+
+ int nRead;
+ while((nRead = in.read(cache)) != -1) {
+ out.write(cache, 0, nRead);
+ out.flush();
+ }
+
+ out.close();
+ in.close();
+ data = out.toByteArray();
+ }
+
+ return data;
+ }
+
+ public static void byteArrayToFile(byte[] bytes, String filePath) throws IOException {
+ InputStream in = new ByteArrayInputStream(bytes);
+ File destFile = new File(filePath);
+ if (!destFile.getParentFile().exists()) {
+ destFile.getParentFile().mkdirs();
+ }
+
+ destFile.createNewFile();
+ OutputStream out = new FileOutputStream(destFile);
+ byte[] cache = new byte[1024];
+ boolean var6 = false;
+
+ int nRead;
+ while((nRead = in.read(cache)) != -1) {
+ out.write(cache, 0, nRead);
+ out.flush();
+ }
+
+ out.close();
+ in.close();
+ }
+}
\ No newline at end of file
diff --git a/itools-core/itools-utils/src/main/java/com/itools/core/utils/ZipUtils.java b/itools-core/itools-utils/src/main/java/com/itools/core/utils/ZipUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..8591326727d639c3e534a23f694e3171ae732f48
--- /dev/null
+++ b/itools-core/itools-utils/src/main/java/com/itools/core/utils/ZipUtils.java
@@ -0,0 +1,56 @@
+package com.itools.core.utils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Iterator;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+public class ZipUtils {
+ private static int BUFFER_SIZE = 1024;
+
+ public ZipUtils() {
+ }
+
+ public static void toZip(List files, OutputStream outputStream) throws RuntimeException {
+ long start = System.currentTimeMillis();
+ ZipOutputStream zipOutputStream = null;
+
+ try {
+ zipOutputStream = new ZipOutputStream(outputStream);
+ Iterator var5 = files.iterator();
+
+ while(var5.hasNext()) {
+ File file = (File)var5.next();
+ byte[] buf = new byte[BUFFER_SIZE];
+ zipOutputStream.putNextEntry(new ZipEntry(file.getName()));
+ FileInputStream in = new FileInputStream(file);
+
+ int len;
+ while((len = in.read(buf)) != -1) {
+ zipOutputStream.write(buf, 0, len);
+ }
+
+ zipOutputStream.closeEntry();
+ in.close();
+ }
+
+ long end = System.currentTimeMillis();
+ System.out.println("压缩完成,耗时:" + (end - start) + " ms");
+ } catch (Exception var17) {
+ throw new RuntimeException("zip error from ZipUtils", var17);
+ } finally {
+ if (zipOutputStream != null) {
+ try {
+ zipOutputStream.close();
+ } catch (IOException var16) {
+ var16.printStackTrace();
+ }
+ }
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/itools-core/pom.xml b/itools-core/pom.xml
index 970ae695e929b9a3e8a60d76d5be712cb1a27a21..b5c7361966f6bfc32a125d106e893fd8240e4ce7 100644
--- a/itools-core/pom.xml
+++ b/itools-core/pom.xml
@@ -34,7 +34,7 @@
3.9.1
8.18.0
1.16.16
- 2.7.0
+ 2.9.2
1.2.30
1.27.0.0
5.1.40
diff --git "a/itools-fms/document/fms\346\216\245\345\217\243\346\226\207\346\241\243.assets/1604555758869.png" "b/itools-fms/document/fms\346\216\245\345\217\243\346\226\207\346\241\243.assets/1604555758869.png"
new file mode 100644
index 0000000000000000000000000000000000000000..0e32b4943355381dfec39417aa8afa398bbd8cd2
Binary files /dev/null and "b/itools-fms/document/fms\346\216\245\345\217\243\346\226\207\346\241\243.assets/1604555758869.png" differ
diff --git "a/itools-fms/document/fms\346\216\245\345\217\243\346\226\207\346\241\243.assets/1604556120012.png" "b/itools-fms/document/fms\346\216\245\345\217\243\346\226\207\346\241\243.assets/1604556120012.png"
new file mode 100644
index 0000000000000000000000000000000000000000..8d7f13ae7c733f6fa572a2c2943233b320256d1d
Binary files /dev/null and "b/itools-fms/document/fms\346\216\245\345\217\243\346\226\207\346\241\243.assets/1604556120012.png" differ
diff --git "a/itools-fms/document/fms\346\216\245\345\217\243\346\226\207\346\241\243.assets/1604556346057.png" "b/itools-fms/document/fms\346\216\245\345\217\243\346\226\207\346\241\243.assets/1604556346057.png"
new file mode 100644
index 0000000000000000000000000000000000000000..44f988f8da16c2abfc259d24ab693495ce0f2020
Binary files /dev/null and "b/itools-fms/document/fms\346\216\245\345\217\243\346\226\207\346\241\243.assets/1604556346057.png" differ
diff --git "a/itools-fms/document/fms\346\216\245\345\217\243\346\226\207\346\241\243.assets/1604556562914.png" "b/itools-fms/document/fms\346\216\245\345\217\243\346\226\207\346\241\243.assets/1604556562914.png"
new file mode 100644
index 0000000000000000000000000000000000000000..dc611f6980a833853d8a2af425eef00397d18359
Binary files /dev/null and "b/itools-fms/document/fms\346\216\245\345\217\243\346\226\207\346\241\243.assets/1604556562914.png" differ
diff --git "a/itools-fms/document/fms\346\216\245\345\217\243\346\226\207\346\241\243.assets/1604556812426.png" "b/itools-fms/document/fms\346\216\245\345\217\243\346\226\207\346\241\243.assets/1604556812426.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d529403d3712a85c91b4b97a45c78f48767e8cba
Binary files /dev/null and "b/itools-fms/document/fms\346\216\245\345\217\243\346\226\207\346\241\243.assets/1604556812426.png" differ
diff --git "a/itools-fms/document/fms\346\216\245\345\217\243\346\226\207\346\241\243.assets/1604558494167.png" "b/itools-fms/document/fms\346\216\245\345\217\243\346\226\207\346\241\243.assets/1604558494167.png"
new file mode 100644
index 0000000000000000000000000000000000000000..4f14c0a225654e62308ed6e39879f51689b026e8
Binary files /dev/null and "b/itools-fms/document/fms\346\216\245\345\217\243\346\226\207\346\241\243.assets/1604558494167.png" differ
diff --git "a/itools-fms/document/fms\346\216\245\345\217\243\346\226\207\346\241\243.assets/1604561499549.png" "b/itools-fms/document/fms\346\216\245\345\217\243\346\226\207\346\241\243.assets/1604561499549.png"
new file mode 100644
index 0000000000000000000000000000000000000000..62202ac704972029a71cf63423b359afbfa63e8f
Binary files /dev/null and "b/itools-fms/document/fms\346\216\245\345\217\243\346\226\207\346\241\243.assets/1604561499549.png" differ
diff --git "a/itools-fms/document/fms\346\216\245\345\217\243\346\226\207\346\241\243.md" "b/itools-fms/document/fms\346\216\245\345\217\243\346\226\207\346\241\243.md"
new file mode 100644
index 0000000000000000000000000000000000000000..a55bd16b5fc2d6ec14e06d0f8c295a69cf011c99
--- /dev/null
+++ "b/itools-fms/document/fms\346\216\245\345\217\243\346\226\207\346\241\243.md"
@@ -0,0 +1,260 @@
+## fms接口文档
+
+### 配置
+
+#### 1.配置文件
+
+```java
+spring:
+ servlet:
+ multipart:
+ # 最大支持文件大小
+ max-file-size: 20MB
+ # 最大支持请求大小
+ max-request-size: 200MB
+ # 上传文件的临时目录
+ location: /home/hash/AppSvr01/installedApps/fsnsh_backend-master/temp
+
+
+fileStoreRootPath: /data/fsnsh/fssFile #文件存储路径,此路径应该是多个FSS服务的共享磁盘
+fileAccessUrlForOutter: http://192.168.0.97:8002/File/
+fileUploadLimitSize: 10 #批量上传限制的个数
+fileMaxRequestSize: 204800 #最大的请求数,单位KB,200MB
+fileMaxFileSize: 20480 #单个文件最大大小,单位KB,20MB
+```
+
+#### 2.执行运行的DDL/DML
+
+DDL在`script`目录下,再执行DML脚本配置文件类型
+
+```sql
+INSERT INTO `fss_business_type`(`id`, `business_type`, `remark`, `fs_size`, `fs_type`, `create_date`, `update_date`) VALUES (1, '01', '文件上传', '102400', 'multipart/form-data,application/octet-stream,text/plain', '2019-08-20 18:48:57.000000', '2019-08-20 18:48:59.000000');
+INSERT INTO `fss_business_type`(`id`, `business_type`, `remark`, `fs_size`, `fs_type`, `create_date`, `update_date`) VALUES (2, '02', 'jar包上传', '102400', 'application/octet-stream,text/plain,multipart/form-data', '2019-08-28 15:24:34.000000', '2019-08-28 15:24:37.000000');
+INSERT INTO `fss_business_type`(`id`, `business_type`, `remark`, `fs_size`, `fs_type`, `create_date`, `update_date`) VALUES (3, 'currency', '通用类型', '102400', 'currency', '2019-10-14 20:21:37.000000', '2019-10-14 20:21:40.000000');
+INSERT INTO `fss_business_type`(`id`, `business_type`, `remark`, `fs_size`, `fs_type`, `create_date`, `update_date`) VALUES (4, '03', 'doc', '102400', 'multipart/form-data; boundary=----WebKitFormBoundaryV9UszO8Om8qv8nNM', '2020-07-30 16:05:31.000000', '2020-07-30 16:05:35.000000');
+
+```
+
+
+
+### 接口
+
+#### 申请文件上传token
+
+接口url:`http://127.0.0.1:8002/UploadToken`
+
+请求方式:POST
+
+接口参数:
+
+| 字段名称 | 类型 | 描述 |
+| ------------ | ------ | -------------------------------------------------------- |
+| businessType | String | 文件类型 |
+| fromSystemId | String | 上传的文件来自哪个子系统,系统编号 |
+| needEncrypt | String | 是否需加密,后续扩展使用,本期不使用,默认否.0:否 1:是 |
+| remark | String | 文件描述信息 |
+
+接口描述:
+
+上传文件,先获取token,token设置有效时间
+
+businessType:文件类型;
+
+fromSystemId:上传的文件来自哪个子系统,系统编号;
+
+needEncrypt:是否需加密,后续扩展使用,本期不使用,默认否.0:否 1:是;
+
+remark:文件描述信息
+
+
+
+#### 单个文件上传
+
+接口url:`http://127.0.0.1:8002/File`
+
+请求方式:POST
+
+接口参数:
+
+| 字段名称 | 类型 | 描述 |
+| ----------- | ------ | ---------------------------------- |
+| file | String | 文件 |
+| uploadToken | String | 上传的文件来自哪个子系统,系统编号 |
+| fileName | String | 自定义文件名,为空选择默认名称 |
+
+接口描述:
+
+
+
+#### 批量上传 文件
+
+接口url:`http://127.0.0.1:8002/FilesPath`
+
+请求方式:POST
+
+接口参数:
+
+| 字段名称 | 类型 | 描述 |
+| ----------- | ------ | ---------------------------------- |
+| files | String | 选取的多个文件 |
+| uploadToken | String | 上传的文件来自哪个子系统,系统编号 |
+
+接口描述:
+
+返回的文件名称对应的文件标识id
+
+uniqueId:文件标识id
+
+fileName:文件名称
+
+```json
+{
+ "returnCode": "0000",
+ "returnMsg": "Success",
+ "nonceStr": "07830f77001141d9bcbb3f42a90481b3",
+ "success": true,
+ "data": [
+ {
+ "uniqueId": "8cbaea82593a417ab530b91ce1c26e74",
+ "fileName": "微信图片_20201105130745 - 副本 - 副本 (3).jpg"
+ },
+ {
+ "uniqueId": "a18210fb568345c4ba883d20704dc87b",
+ "fileName": "微信图片_20201105130745 - 副本 - 副本 - 副本.jpg"
+ }
+ ]
+}
+```
+
+
+
+
+
+#### 获取文件访问路径
+
+接口url:`http://127.0.0.1:8002/FilePath`
+
+请求方式:POST
+
+接口参数:
+
+| 字段名称 | 类型 | 描述 |
+| -------------- | ------ | --------------------------- |
+| uniqueId | String | 文件的唯一ID |
+| expiredTime | Long | 有效时长,单位分钟 |
+| maxAccessCount | Long | 最大访问次数 |
+| type | String | 文件下载 download/展示 show |
+
+接口描述:
+
+获取该文件的访问的路径,也是需要根据传入的过期时间,访问类型等等
+
+
+
+#### 获取多个文件访问路径
+
+接口url:`http://127.0.0.1:8002/FilesPath`
+
+请求方式:POST
+
+接口参数:
+
+| 字段名称 | 类型 | 描述 |
+| -------------- | -------- | --------------------------- |
+| uniqueIds | String[] | 文件的唯一IDS,数组 |
+| expiredTime | Long | 有效时长,单位分钟 |
+| maxAccessCount | Long | 最大访问次数 |
+| type | String | 文件下载 download/展示 show |
+
+接口描述:
+
+获取该文件的访问的路径,也是需要根据传入的过期时间,访问类型等等
+
+```json
+{
+ "returnCode": "0000",
+ "returnMsg": "Success",
+ "nonceStr": "22487d32278e463b9cc6f3989df230a9",
+ "success": true,
+ "data": [
+ {
+ "uniqueId": "1f449166a6e141f9b3b2dce5aa4e0b6b",
+ "path": "http://192.168.0.97:8002/File/1f449166a6e141f9b3b2dce5aa4e0b6b?fileAccessToken=a58f0d6969a945a795dd8cfb3ea85d26"
+ },
+ {
+ "uniqueId": "a18210fb568345c4ba883d20704dc87b",
+ "path": "http://192.168.0.97:8002/File/a18210fb568345c4ba883d20704dc87b?fileAccessToken=44e79a91414d4692ac0224452e0d2c3d"
+ }
+ ]
+}
+```
+
+
+
+
+
+#### 下载、访问文件
+
+接口url:`http://127.0.0.1:8002/File`
+
+请求方式:GET
+
+接口参数:
+
+| 字段名称 | 类型 | 描述 |
+| --------------- | ------ | ------------- |
+| uniqueId | String | 文件的唯一ID |
+| fileAccessToken | String | 文件访问token |
+
+接口描述:
+
+访问文件
+
+#### 获取base64
+
+接口url:`http://127.0.0.1:8002/File/getFileBase64`
+
+请求方式:GET
+
+接口参数:
+
+| 字段名称 | 类型 | 描述 |
+| -------- | ------ | ------------ |
+| uniqueId | String | 文件的唯一ID |
+
+接口描述:
+
+根据文件标识id返回base64的文件
+
+#### 获取文件记录信息
+
+接口url:`http://127.0.0.1:8002/fssRecord`
+
+请求方式:GET
+
+接口参数:
+
+| 字段名称 | 类型 | 描述 |
+| -------- | ------ | ------------ |
+| uniqueId | String | 文件的唯一ID |
+
+接口描述:
+
+获取文件记录信息 (内部调用)
+
+#### 下载zip压缩文件接口
+
+接口url:`http://127.0.0.1:8002/download/zip`
+
+请求方式:POST
+
+接口参数:
+
+| 字段名称 | 类型 | 描述 |
+| --------- | -------- | ------------- |
+| uniqueIds | String[] | 文件的唯一IDS |
+| zipName | String | 压缩文件名称 |
+
+接口描述:
+
+根据文件标识id下载对应的标识的文件,返回zip的压缩文件
\ No newline at end of file
diff --git a/itools-fms/itools-fms-core/pom.xml b/itools-fms/itools-fms-core/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c32b56eb36cf39f34b6111bdb270b496d517f9f4
--- /dev/null
+++ b/itools-fms/itools-fms-core/pom.xml
@@ -0,0 +1,50 @@
+
+
+
+ itools-fms
+ com.itools.core
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ itools-fms-core
+
+
+ com.itools.core
+ itools-common
+ 1.0-SNAPSHOT
+ compile
+
+
+ com.itools.core
+ itools-fms-model
+ 1.0-SNAPSHOT
+
+
+
+ io.springfox
+ springfox-swagger2
+ 2.9.2
+
+
+ io.springfox
+ springfox-swagger-ui
+ 2.9.2
+
+
+ com.github.xiaoymin
+ swagger-bootstrap-ui
+ 1.9.6
+
+
+ io.minio
+ minio
+ 7.0.2
+
+
+
+
+
+
\ No newline at end of file
diff --git a/itools-fms/itools-fms-core/src/main/java/com/itools/core/annotation/FileStrategy.java b/itools-fms/itools-fms-core/src/main/java/com/itools/core/annotation/FileStrategy.java
new file mode 100644
index 0000000000000000000000000000000000000000..57665e555d4c4964703bbdf989cfbf674310ff61
--- /dev/null
+++ b/itools-fms/itools-fms-core/src/main/java/com/itools/core/annotation/FileStrategy.java
@@ -0,0 +1,24 @@
+package com.itools.core.annotation;
+
+import com.itools.core.em.StrategyType;
+import org.springframework.stereotype.Service;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @project: itools-backend
+ * @description: 选择文件系统的策略注解
+ * @author: XUCHANG
+ * @create: 2021-04-01 15:57
+ */
+@Service
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface FileStrategy {
+
+ StrategyType value();
+
+}
diff --git a/itools-fms/itools-fms-core/src/main/java/com/itools/core/config/MinioConfig.java b/itools-fms/itools-fms-core/src/main/java/com/itools/core/config/MinioConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..cb3ebe48f4ff6e7330e198b6e77c00e3f84a6f51
--- /dev/null
+++ b/itools-fms/itools-fms-core/src/main/java/com/itools/core/config/MinioConfig.java
@@ -0,0 +1,49 @@
+package com.itools.core.config;
+
+import io.minio.MinioClient;
+import io.minio.errors.InvalidEndpointException;
+import io.minio.errors.InvalidPortException;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.stereotype.Component;
+
+/**
+ * @project: itools-backend
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-04-01 16:06
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "fms.minio")
+public class MinioConfig {
+
+ @ApiModelProperty("endPoint是一个URL,域名,IPv4或者IPv6地址")
+ private String endpoint;
+
+ @ApiModelProperty("TCP/IP端口号")
+ private int port;
+
+ @ApiModelProperty("accessKey类似于用户ID,用于唯一标识你的账户")
+ private String accessKey;
+
+ @ApiModelProperty("secretKey是你账户的密码")
+ private String secretKey;
+
+ @ApiModelProperty("如果是true,则用的是https而不是http,默认值是true")
+ private Boolean secure;
+
+ @ApiModelProperty("默认存储桶")
+ private String bucketName;
+
+ @ApiModelProperty("配置目录")
+ private String configDir;
+
+ @Bean
+ public MinioClient getMinioClient() throws InvalidEndpointException, InvalidPortException {
+ MinioClient minioClient = new MinioClient(endpoint, port, accessKey, secretKey,secure);
+ return minioClient;
+ }
+}
\ No newline at end of file
diff --git a/itools-fms/itools-fms-core/src/main/java/com/itools/core/config/MybatisPlusConfig.java b/itools-fms/itools-fms-core/src/main/java/com/itools/core/config/MybatisPlusConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..56a51101d22b2a1fbbb89ddb08bd311c054e7111
--- /dev/null
+++ b/itools-fms/itools-fms-core/src/main/java/com/itools/core/config/MybatisPlusConfig.java
@@ -0,0 +1,32 @@
+package com.itools.core.config;
+
+import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+/**
+ * @project: itools-backend
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-04-01 16:06
+ */
+@Configuration
+@EnableTransactionManagement
+@MapperScan("com.itools.core.mapper")
+public class MybatisPlusConfig {
+ @Bean
+ public PaginationInterceptor paginationInterceptor() {
+
+ PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
+ // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false
+ // paginationInterceptor.setOverflow(false);
+ // 设置最大单页限制数量,默认 500 条,-1 不受限制
+ // paginationInterceptor.setLimit(500);
+ // 开启 count 的 join 优化,只针对部分 left join
+ paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
+ return paginationInterceptor;
+ }
+}
diff --git a/itools-fms/itools-fms-core/src/main/java/com/itools/core/config/SwaggerAutoConfiguration.java b/itools-fms/itools-fms-core/src/main/java/com/itools/core/config/SwaggerAutoConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..ddd193ef8a2a939e7eadeb0227965e08f58185e6
--- /dev/null
+++ b/itools-fms/itools-fms-core/src/main/java/com/itools/core/config/SwaggerAutoConfiguration.java
@@ -0,0 +1,41 @@
+//package com.itools.core.config;
+//
+//import io.swagger.annotations.ApiOperation;
+//import io.swagger.annotations.Contact;
+//import org.springframework.context.annotation.Bean;
+//import org.springframework.context.annotation.Configuration;
+//import springfox.documentation.builders.ApiInfoBuilder;
+//import springfox.documentation.builders.PathSelectors;
+//import springfox.documentation.builders.RequestHandlerSelectors;
+//import springfox.documentation.service.ApiInfo;
+//import springfox.documentation.spi.DocumentationType;
+//import springfox.documentation.spring.web.plugins.Docket;
+//import springfox.documentation.swagger2.annotations.EnableSwagger2;
+//
+//@Configuration
+//@EnableSwagger2
+//public class SwaggerAutoConfiguration{
+//
+// @Bean
+// public Docket createRestApi() {
+// return new Docket(DocumentationType.SWAGGER_2)
+// .groupName("")
+// .apiInfo(apiInfo())
+// .select()
+// .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
+// .paths(PathSelectors.any())
+// .build();
+// }
+//
+//
+// private ApiInfo apiInfo() {
+// return new ApiInfoBuilder()
+// .title("**平台对外接口")
+// .description("1.提供**后台使用的接口 2.提供对其他服务调用的服务")
+//// .contact(new Contact("xtj332", "https://blog.csdn.net/xtj332", "xtj332111@163.com"))
+// .version("1.0")
+// .build();
+// }
+//
+//
+//}
\ No newline at end of file
diff --git a/itools-fms/itools-fms-core/src/main/java/com/itools/core/config/SwaggerConfig.java b/itools-fms/itools-fms-core/src/main/java/com/itools/core/config/SwaggerConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..b19297eadf3b6f2ccc430e53829d9279364240af
--- /dev/null
+++ b/itools-fms/itools-fms-core/src/main/java/com/itools/core/config/SwaggerConfig.java
@@ -0,0 +1,108 @@
+//package com.itools.core.config;
+//
+//import io.swagger.annotations.ApiOperation;
+//import org.springframework.context.annotation.Bean;
+//import org.springframework.context.annotation.Configuration;
+//import org.springframework.context.annotation.Profile;
+//import springfox.documentation.builders.ApiInfoBuilder;
+//import springfox.documentation.builders.ParameterBuilder;
+//import springfox.documentation.builders.PathSelectors;
+//import springfox.documentation.builders.RequestHandlerSelectors;
+//import springfox.documentation.schema.ModelRef;
+//import springfox.documentation.service.*;
+//import springfox.documentation.spi.DocumentationType;
+//import springfox.documentation.spi.service.contexts.SecurityContext;
+//import springfox.documentation.spring.web.plugins.Docket;
+//import springfox.documentation.swagger2.annotations.EnableSwagger2;
+//
+//import java.time.LocalTime;
+//import java.util.ArrayList;
+//import java.util.List;
+//
+///**
+// * SwaggerConfig api文档地址:/swagger-ui.html 或者 /doc.html
+// */
+////指定在某些环境启用swagger的配置
+//@Profile({
+// "dev","test"
+//})
+//// swagger暂不支持webflux
+//@Configuration
+//@EnableSwagger2
+//public class SwaggerConfig {
+// @Bean
+// public Docket createRestApi() {
+// //定义swagger全局入参token
+// ParameterBuilder tokenPar = new ParameterBuilder();
+// List pars = new ArrayList();
+// tokenPar.name("Authorization").description("用户令牌(无须鉴权的可以不传 格式:bearer 密文串").modelRef(new ModelRef("string"))
+// .parameterType("header").required(false).build();
+// pars.add(tokenPar.build());
+//
+// return new Docket(DocumentationType.SWAGGER_2)
+// .directModelSubstitute(LocalTime.class, String.class)
+// //.groupName("normal") //使用默认分组,便于网关层的swagger转发
+// .apiInfo(defaultTitleInfo()) //可设置默认分组api顶部说明文字
+// .useDefaultResponseMessages(false)
+// .select()
+// .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
+// //只允许生成ApiOperation注解的方法,其他系统内部用的api可隐藏
+// .build();
+//// //.globalOperationParameters(pars);
+//// //设置安全模式,swagger全局设置token
+//// .securitySchemes(securitySchemes())
+//// .securityContexts(securityContexts());
+//
+// }
+//
+// /**
+// * 安全模式,这里指定token通过Authorization头请求头传递
+// */
+// private List securitySchemes()
+// {
+// List apiKeyList = new ArrayList<>();
+// apiKeyList.add(new ApiKey("Authorization", "Authorization", "header"));
+// return apiKeyList;
+// }
+//
+// /**
+// * 安全上下文
+// */
+// private List securityContexts()
+// {
+// List securityContexts = new ArrayList<>();
+// securityContexts.add(
+// SecurityContext.builder()
+// .securityReferences(defaultAuth())
+// .forPaths(PathSelectors.regex("^(?!auth).*$"))
+// .build());
+// return securityContexts;
+// }
+//
+// /**
+// * 默认的安全上引用
+// */
+// private List defaultAuth()
+// {
+// AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
+// AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
+// authorizationScopes[0] = authorizationScope;
+// List securityReferences = new ArrayList<>();
+// securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
+// return securityReferences;
+// }
+//
+// /**
+// * 默认标题信息
+// * @return -
+// */
+// private ApiInfo defaultTitleInfo() {
+// return new ApiInfoBuilder()
+// .title("接口地址使用Base URL")//大标题
+// .description("· 接口成功返回:{\"success\": true,\"code\": 20000,\"message\": \"成功\",\"data\": null} "
+// + "
· 失败的返回:{\"success\": false,\"code\": 50002,\"message\": \"算术运算异常\",\"data\": null} "
+// )//详细描述
+// .version("1.0")//版本
+// .build();
+// }
+//}
\ No newline at end of file
diff --git a/itools-fms/itools-fms-core/src/main/java/com/itools/core/context/FileStrategyServiceContext.java b/itools-fms/itools-fms-core/src/main/java/com/itools/core/context/FileStrategyServiceContext.java
new file mode 100644
index 0000000000000000000000000000000000000000..b0a54381097ce8e213354431819b90382201aa26
--- /dev/null
+++ b/itools-fms/itools-fms-core/src/main/java/com/itools/core/context/FileStrategyServiceContext.java
@@ -0,0 +1,52 @@
+package com.itools.core.context;
+
+import com.itools.core.em.StrategyType;
+import com.itools.core.service.FileManagerService;
+import lombok.Getter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @project: itools-backend
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-04-01 16:02
+ */
+@Component
+public class FileStrategyServiceContext {
+ @Autowired
+ private Environment environment;
+ @Getter
+ private final static Map fileServiceMap;
+
+ static {
+ fileServiceMap = new HashMap<>();
+ }
+
+ public FileManagerService get(String type) {
+ return fileServiceMap.get(type);
+ }
+
+ /**
+ * 获取默认或者配置的文件服务策略
+ * @return
+ */
+ public FileManagerService get(){
+ boolean containsProperty = environment.containsProperty("fms.strategy");
+ if (containsProperty){
+ fileServiceMap.get(environment.getProperty("fms.strategy"));
+ }
+ return fileServiceMap.get(StrategyType.NIO.getType());
+ }
+
+ public void put(String type, FileManagerService calcService) {
+ fileServiceMap.put(type, calcService);
+ }
+ public Map getMap(){
+ return fileServiceMap;
+ }
+}
diff --git a/itools-fms/itools-fms-core/src/main/java/com/itools/core/em/FmsCodeBean.java b/itools-fms/itools-fms-core/src/main/java/com/itools/core/em/FmsCodeBean.java
new file mode 100644
index 0000000000000000000000000000000000000000..f2db4555a7b3f9b8183e1cdfe7319519bef238dc
--- /dev/null
+++ b/itools-fms/itools-fms-core/src/main/java/com/itools/core/em/FmsCodeBean.java
@@ -0,0 +1,80 @@
+package com.itools.core.em;
+
+
+import com.itools.core.code.SystemCode;
+
+/**
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-03-28 15:51
+ */
+@SystemCode
+public class FmsCodeBean {
+
+ public enum FmsCode {
+ /**
+ * 文件系统内部错误
+ */
+ FAIL("FSS01", "文件系统内部错误"),
+ /**
+ * BUSINESS_TYPE不存在
+ */
+ ERROR_BUSINESS_TYPE_NOT_EXIST("FSS02", "BUSINESS_TYPE不存在"),
+ /**
+ * 文件不能为空
+ */
+ ERROR_FILE_IS_NULL("FSS11", "文件不能为空"),
+ /**
+ * 参数错误
+ */
+ ERROR_PARAMS("FSS12", "参数错误"),
+ /**
+ * 文件上传时间限定超时
+ */
+ ERROR_TIMEOUT("FSS13", "文件上传时间限定超时"),
+ /**
+ * 文件大小超过限制
+ */
+ ERROR_FILESIZE_OUT_OFF_LIMIT("FSS14", "文件大小超过限制"),
+ /**
+ * 该文件类型不允许
+ */
+ ERROR_FILETYPE("FSS15", "该文件类型不允许"),
+ /**
+ * 文件ID非法
+ */
+ INVALID_FS_UNIQUE_ID("FSS21", "文件ID非法"),
+
+ ERROR_TRANS_BASE64("FSS22", "文件转base64失败"),
+ /**
+ * 鉴权失败
+ */
+ INVALID_FS_TOKEN("401", "鉴权失败"),
+ /**
+ * 找不到该文件
+ * 错误码直接放到response中,所以按照http的规范设置
+ */
+ NOT_EXIST_FILE("404", "找不到该文件"),
+
+ FILE_LIMIT_SIZE("FSS23", "文件上传个数受限"),
+
+ FILE_MULTIPART_UPLOAD("FSS24", "批量上传文件失败"),
+ ;
+
+ public final String code;
+ public final String message;
+
+ FmsCode(String code, String message) {
+ this.code = code;
+ this.message = message;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+ }
+}
diff --git a/itools-fms/itools-fms-core/src/main/java/com/itools/core/em/FmsConstants.java b/itools-fms/itools-fms-core/src/main/java/com/itools/core/em/FmsConstants.java
new file mode 100644
index 0000000000000000000000000000000000000000..5322ffce67d7c383e291a42a2ebab3e6e39909d1
--- /dev/null
+++ b/itools-fms/itools-fms-core/src/main/java/com/itools/core/em/FmsConstants.java
@@ -0,0 +1,13 @@
+package com.itools.core.em;
+
+/**
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-03-28 15:51
+ */
+public interface FmsConstants {
+
+ String FSS_RECORD_ID_SEQ_NAME="FSS:FssRecord:ID";
+
+
+}
diff --git a/itools-fms/itools-fms-core/src/main/java/com/itools/core/em/StrategyType.java b/itools-fms/itools-fms-core/src/main/java/com/itools/core/em/StrategyType.java
new file mode 100644
index 0000000000000000000000000000000000000000..85be616086b5a0f05c0475d1c42b7a22476079a8
--- /dev/null
+++ b/itools-fms/itools-fms-core/src/main/java/com/itools/core/em/StrategyType.java
@@ -0,0 +1,37 @@
+package com.itools.core.em;
+
+import com.itools.core.utils.StringUtils;
+
+/**
+ * @project: itools-backend
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-04-01 16:02
+ */
+public enum StrategyType {
+ NIO("nio", "NIO","nioFileManagerServiceImpl"),
+ MINIO("minio", "miniio文件系统","minioFileManagerServiceImpl"),
+ FASTDFS("fastdfs", "fastdfs文件系统","fastDfsFileManagerServiceImpl");
+ private String type;
+ private String desc;
+ private String beanName;
+
+ StrategyType(String type, String desc,String beanName) {
+ this.type = type;
+ this.desc = desc;
+ this.beanName = beanName;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public static String getType(String beanName) {
+ for (StrategyType strategyType : StrategyType.values()){
+ if (StringUtils.equals(beanName,strategyType.beanName)){
+ return strategyType.type;
+ }
+ }
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/itools-fms/itools-fms-core/src/main/java/com/itools/core/listener/FileStrategyListener.java b/itools-fms/itools-fms-core/src/main/java/com/itools/core/listener/FileStrategyListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..06b83d88643b09bfa6cd5315fbd00b625e6ff2d0
--- /dev/null
+++ b/itools-fms/itools-fms-core/src/main/java/com/itools/core/listener/FileStrategyListener.java
@@ -0,0 +1,44 @@
+package com.itools.core.listener;
+
+import com.itools.core.annotation.FileStrategy;
+import com.itools.core.context.FileStrategyServiceContext;
+import com.itools.core.em.StrategyType;
+import com.itools.core.service.FileManagerService;
+import com.itools.core.utils.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.event.ContextRefreshedEvent;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @project: itools-backend
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-04-01 16:06
+ */
+@Component
+public class FileStrategyListener implements ApplicationListener {
+ @Autowired
+ private FileStrategyServiceContext fileStrategyServiceContext;
+
+ /**
+ * 监听类
+ * @param contextRefreshedEvent
+ */
+ @Override
+ public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
+
+ Map beans = contextRefreshedEvent.getApplicationContext().getBeansOfType(FileManagerService.class);
+ beans.forEach((k, service) -> {
+ String type = StrategyType.getType(k);
+ fileStrategyServiceContext.put(type, service);
+// if (StringUtils.equals(k,))
+// Class clazz = service.getClass();
+// FileStrategy fileStrategy = (FileStrategy)clazz.getAnnotation(FileStrategy.class);
+// fileStrategyServiceContext.put(fileStrategy.value().getType(), service);
+ });
+ }
+}
diff --git a/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/FileManagerService.java b/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/FileManagerService.java
new file mode 100644
index 0000000000000000000000000000000000000000..e2aab474688e6f09dfbf6bf2ce8e78ee9d2814a4
--- /dev/null
+++ b/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/FileManagerService.java
@@ -0,0 +1,27 @@
+package com.itools.core.service;
+
+import com.itools.core.base.CommonResult;
+import com.itools.core.param.FmsUploadTokenParam;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-04-01 15:44
+ */
+public interface FileManagerService {
+ /**
+ * 批量上传文件
+ * @param files 文件
+ * @param param 上传的参数
+ * @return
+ */
+ CommonResult mutipartUploadFiles(MultipartFile[] files, FmsUploadTokenParam param);
+ /**
+ * 单个上传文件
+ * @param file 文件
+ * @param param 上传的参数
+ * @return
+ */
+ CommonResult mutipartUploadFiles(MultipartFile file, FmsUploadTokenParam param);
+}
diff --git a/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/impl/FastDfsFileManagerServiceImpl.java b/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/impl/FastDfsFileManagerServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..a12356c20ae6b9e10dc00ba6edd3e7c6364cc3f7
--- /dev/null
+++ b/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/impl/FastDfsFileManagerServiceImpl.java
@@ -0,0 +1,40 @@
+package com.itools.core.service.impl;
+
+import com.itools.core.annotation.FileStrategy;
+import com.itools.core.base.CommonResult;
+import com.itools.core.em.StrategyType;
+import com.itools.core.param.FmsUploadTokenParam;
+import com.itools.core.service.FileManagerService;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * @project: itools-backend
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-04-01 16:17
+ */
+@FileStrategy(value = StrategyType.FASTDFS)
+public class FastDfsFileManagerServiceImpl implements FileManagerService {
+ /**
+ * 批量上传文件
+ * @param files 文件
+ * @param param 上传的参数
+ * @return
+ */
+ @Override
+ public CommonResult mutipartUploadFiles(MultipartFile[] files, FmsUploadTokenParam param) {
+ return CommonResult.success(StrategyType.FASTDFS.getType());
+ }
+
+ /**
+ * 单个上传文件
+ *
+ * @param file 文件
+ * @param param 上传的参数
+ * @return
+ */
+ @Override
+ public CommonResult mutipartUploadFiles(MultipartFile file, FmsUploadTokenParam param) {
+ return null;
+ }
+}
diff --git a/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/impl/MinioFileManagerServiceImpl.java b/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/impl/MinioFileManagerServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..062a426f8e2af6341143ef1720f45cfcff9889b3
--- /dev/null
+++ b/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/impl/MinioFileManagerServiceImpl.java
@@ -0,0 +1,40 @@
+package com.itools.core.service.impl;
+
+import com.itools.core.annotation.FileStrategy;
+import com.itools.core.base.CommonResult;
+import com.itools.core.em.StrategyType;
+import com.itools.core.param.FmsUploadTokenParam;
+import com.itools.core.service.FileManagerService;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * @project: itools-backend
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-04-01 16:17
+ */
+@FileStrategy(value = StrategyType.MINIO)
+public class MinioFileManagerServiceImpl implements FileManagerService {
+ /**
+ * 批量上传文件
+ * @param files 文件
+ * @param param 上传的参数
+ * @return
+ */
+ @Override
+ public CommonResult mutipartUploadFiles(MultipartFile[] files, FmsUploadTokenParam param) {
+ return CommonResult.success(StrategyType.MINIO.getType());
+ }
+
+ /**
+ * 单个上传文件
+ *
+ * @param file 文件
+ * @param param 上传的参数
+ * @return
+ */
+ @Override
+ public CommonResult mutipartUploadFiles(MultipartFile file, FmsUploadTokenParam param) {
+ return null;
+ }
+}
diff --git a/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/impl/NioFileManagerServiceImpl.java b/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/impl/NioFileManagerServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..dea9526e4865e4f0ed6d417e258d2970505a868e
--- /dev/null
+++ b/itools-fms/itools-fms-core/src/main/java/com/itools/core/service/impl/NioFileManagerServiceImpl.java
@@ -0,0 +1,40 @@
+package com.itools.core.service.impl;
+
+import com.itools.core.annotation.FileStrategy;
+import com.itools.core.base.CommonResult;
+import com.itools.core.em.StrategyType;
+import com.itools.core.param.FmsUploadTokenParam;
+import com.itools.core.service.FileManagerService;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * @project: itools-backend
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-04-01 16:17
+ */
+@FileStrategy(value = StrategyType.NIO)
+public class NioFileManagerServiceImpl implements FileManagerService {
+ /**
+ * 批量上传文件
+ * @param files 文件
+ * @param param 上传的参数
+ * @return
+ */
+ @Override
+ public CommonResult mutipartUploadFiles(MultipartFile[] files, FmsUploadTokenParam param) {
+ return CommonResult.success(StrategyType.NIO.getType());
+ }
+
+ /**
+ * 单个上传文件
+ *
+ * @param file 文件
+ * @param param 上传的参数
+ * @return
+ */
+ @Override
+ public CommonResult mutipartUploadFiles(MultipartFile file, FmsUploadTokenParam param) {
+ return null;
+ }
+}
diff --git a/itools-fms/itools-fms-core/src/main/java/com/itools/core/utils/MinioUtil.java b/itools-fms/itools-fms-core/src/main/java/com/itools/core/utils/MinioUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..561de3f73ae1bcef3ae8497f263204bc3fcfb982
--- /dev/null
+++ b/itools-fms/itools-fms-core/src/main/java/com/itools/core/utils/MinioUtil.java
@@ -0,0 +1,430 @@
+package com.itools.core.utils;
+
+import io.minio.MinioClient;
+import io.minio.ObjectStat;
+import io.minio.PutObjectOptions;
+import io.minio.Result;
+import io.minio.errors.ErrorResponseException;
+import io.minio.errors.InvalidExpiresRangeException;
+import io.minio.messages.Bucket;
+import io.minio.messages.DeleteError;
+import io.minio.messages.Item;
+import lombok.SneakyThrows;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletResponse;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @project: itools-backend
+ * @description: 存储桶命名要求
+ * 存储桶的命名需符合以下一个或多个规则
+ *
+ * 存储桶名称的长度介于 3 和 63 个字符之间,并且只能包含小写字母、数字、句点和短划线。
+ * 存储桶名称中的每个标签必须以小写字母或数字开头。
+ * 存储桶名称不能包含下划线、以短划线结束、包含连续句点或在句点旁边使用短划线。
+ * 存储桶名称不能采用 IP 地址格式 (198.51.100.24)。
+ * 存储桶用作可公开访问的 URL,因此您选择的存储桶名称必须具有全局唯一性。如果您选择的名称已被其他一些帐户用于创建存储桶,则必须使用其他名称。
+ * @author: XUCHANG
+ * @create: 2021-04-01 16:06
+ */
+@Component
+public class MinioUtil {
+
+ @Autowired
+ private MinioClient minioClient;
+
+ private static final int DEFAULT_EXPIRY_TIME = 7 * 24 * 3600;
+
+ /**
+ * 检查存储桶是否存在
+ *
+ * @param bucketName 存储桶名称
+ * @return
+ */
+ @SneakyThrows
+ public boolean bucketExists(String bucketName) {
+ boolean flag = false;
+ flag = minioClient.bucketExists(bucketName);
+ if (flag) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 创建存储桶
+ *
+ * @param bucketName 存储桶名称
+ */
+ @SneakyThrows
+ public boolean makeBucket(String bucketName) {
+ boolean flag = bucketExists(bucketName);
+ if (!flag) {
+ minioClient.makeBucket(bucketName);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * 列出所有存储桶名称
+ *
+ * @return
+ */
+ @SneakyThrows
+ public List listBucketNames() {
+ List bucketList = listBuckets();
+ List bucketListName = new ArrayList<>();
+ for (Bucket bucket : bucketList) {
+ bucketListName.add(bucket.name());
+ }
+ return bucketListName;
+ }
+
+ /**
+ * 列出所有存储桶
+ *
+ * @return
+ */
+ @SneakyThrows
+ public List listBuckets() {
+ return minioClient.listBuckets();
+ }
+
+ /**
+ * 删除存储桶
+ *
+ * @param bucketName 存储桶名称
+ * @return
+ */
+ @SneakyThrows
+ public boolean removeBucket(String bucketName) {
+ boolean flag = bucketExists(bucketName);
+ if (flag) {
+ Iterable> myObjects = listObjects(bucketName);
+ for (Result- result : myObjects) {
+ Item item = result.get();
+ // 有对象文件,则删除失败
+ if (item.size() > 0) {
+ return false;
+ }
+ }
+ // 删除存储桶,注意,只有存储桶为空时才能删除成功。
+ minioClient.removeBucket(bucketName);
+ flag = bucketExists(bucketName);
+ if (!flag) {
+ return true;
+ }
+
+ }
+ return false;
+ }
+
+ /**
+ * 列出存储桶中的所有对象名称
+ *
+ * @param bucketName 存储桶名称
+ * @return
+ */
+ @SneakyThrows
+ public List listObjectNames(String bucketName) {
+ List listObjectNames = new ArrayList<>();
+ boolean flag = bucketExists(bucketName);
+ if (flag) {
+ Iterable> myObjects = listObjects(bucketName);
+ for (Result
- result : myObjects) {
+ Item item = result.get();
+ listObjectNames.add(item.objectName());
+ }
+ }
+ return listObjectNames;
+ }
+
+ /**
+ * 列出存储桶中的所有对象
+ *
+ * @param bucketName 存储桶名称
+ * @return
+ */
+ @SneakyThrows
+ public Iterable> listObjects(String bucketName) {
+ boolean flag = bucketExists(bucketName);
+ if (flag) {
+ return minioClient.listObjects(bucketName);
+ }
+ return null;
+ }
+
+ /**
+ * 通过文件上传到对象
+ *
+ * @param bucketName 存储桶名称
+ * @param objectName 存储桶里的对象名称
+ * @param fileName File name
+ * @return
+ */
+ @SneakyThrows
+ public boolean putObject(String bucketName, String objectName, String fileName) {
+ boolean flag = bucketExists(bucketName);
+ if (flag) {
+ minioClient.putObject(bucketName, objectName, fileName, null);
+ ObjectStat statObject = statObject(bucketName, objectName);
+ if (statObject != null && statObject.length() > 0) {
+ return true;
+ }
+ }
+ return false;
+
+ }
+
+ /**
+ * 文件上传
+ *
+ * @param bucketName
+ * @param multipartFile
+ */
+ @SneakyThrows
+ public void putObject(String bucketName, MultipartFile multipartFile, String filename) {
+ PutObjectOptions putObjectOptions = new PutObjectOptions(multipartFile.getSize(), PutObjectOptions.MIN_MULTIPART_SIZE);
+ putObjectOptions.setContentType(multipartFile.getContentType());
+ minioClient.putObject(bucketName, filename, multipartFile.getInputStream(), putObjectOptions);
+ }
+
+ /**
+ * 通过InputStream上传对象
+ *
+ * @param bucketName 存储桶名称
+ * @param objectName 存储桶里的对象名称
+ * @param stream 要上传的流
+ * @return
+ */
+ @SneakyThrows
+ public boolean putObject(String bucketName, String objectName, InputStream stream) {
+ boolean flag = bucketExists(bucketName);
+ if (flag) {
+ minioClient.putObject(bucketName, objectName, stream, new PutObjectOptions(stream.available(), -1));
+ ObjectStat statObject = statObject(bucketName, objectName);
+ if (statObject != null && statObject.length() > 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 以流的形式获取一个文件对象
+ *
+ * @param bucketName 存储桶名称
+ * @param objectName 存储桶里的对象名称
+ * @return
+ */
+ @SneakyThrows
+ public InputStream getObject(String bucketName, String objectName) {
+ boolean flag = bucketExists(bucketName);
+ if (flag) {
+ ObjectStat statObject = statObject(bucketName, objectName);
+ if (statObject != null && statObject.length() > 0) {
+ InputStream stream = minioClient.getObject(bucketName, objectName);
+ return stream;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * 以流的形式获取一个文件对象(断点下载)
+ *
+ * @param bucketName 存储桶名称
+ * @param objectName 存储桶里的对象名称
+ * @param offset 起始字节的位置
+ * @param length 要读取的长度 (可选,如果无值则代表读到文件结尾)
+ * @return
+ */
+ @SneakyThrows
+ public InputStream getObject(String bucketName, String objectName, long offset, Long length) {
+ boolean flag = bucketExists(bucketName);
+ if (flag) {
+ ObjectStat statObject = statObject(bucketName, objectName);
+ if (statObject != null && statObject.length() > 0) {
+ InputStream stream = minioClient.getObject(bucketName, objectName, offset, length);
+ return stream;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * 下载并将文件保存到本地
+ *
+ * @param bucketName 存储桶名称
+ * @param objectName 存储桶里的对象名称
+ * @param fileName File name
+ * @return
+ */
+ @SneakyThrows
+ public boolean getObject(String bucketName, String objectName, String fileName) {
+ boolean flag = bucketExists(bucketName);
+ if (flag) {
+ ObjectStat statObject = statObject(bucketName, objectName);
+ if (statObject != null && statObject.length() > 0) {
+ minioClient.getObject(bucketName, objectName, fileName);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 删除一个对象
+ *
+ * @param bucketName 存储桶名称
+ * @param objectName 存储桶里的对象名称
+ */
+ @SneakyThrows
+ public boolean removeObject(String bucketName, String objectName) {
+ boolean flag = bucketExists(bucketName);
+ if (flag) {
+ minioClient.removeObject(bucketName, objectName);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 删除指定桶的多个文件对象,返回删除错误的对象列表,全部删除成功,返回空列表
+ *
+ * @param bucketName 存储桶名称
+ * @param objectNames 含有要删除的多个object名称的迭代器对象
+ * @return
+ */
+ @SneakyThrows
+ public List removeObject(String bucketName, List objectNames) {
+ List deleteErrorNames = new ArrayList<>();
+ boolean flag = bucketExists(bucketName);
+ if (flag) {
+ Iterable> results = minioClient.removeObjects(bucketName, objectNames);
+ for (Result result : results) {
+ DeleteError error = result.get();
+ deleteErrorNames.add(error.objectName());
+ }
+ }
+ return deleteErrorNames;
+ }
+
+ /**
+ * 生成一个给HTTP GET请求用的presigned URL。
+ * 浏览器/移动端的客户端可以用这个URL进行下载,即使其所在的存储桶是私有的。这个presigned URL可以设置一个失效时间,默认值是7天。
+ *
+ * @param bucketName 存储桶名称
+ * @param objectName 存储桶里的对象名称
+ * @param expires 失效时间(以秒为单位),默认是7天,不得大于七天
+ * @return
+ */
+ @SneakyThrows
+ public String presignedGetObject(String bucketName, String objectName, Integer expires) {
+ boolean flag = bucketExists(bucketName);
+ String url = "";
+ if (flag) {
+ if (expires < 1 || expires > DEFAULT_EXPIRY_TIME) {
+ throw new InvalidExpiresRangeException(expires,
+ "expires must be in range of 1 to " + DEFAULT_EXPIRY_TIME);
+ }
+ url = minioClient.presignedGetObject(bucketName, objectName, expires);
+ }
+ return url;
+ }
+
+ /**
+ * 生成一个给HTTP PUT请求用的presigned URL。
+ * 浏览器/移动端的客户端可以用这个URL进行上传,即使其所在的存储桶是私有的。这个presigned URL可以设置一个失效时间,默认值是7天。
+ *
+ * @param bucketName 存储桶名称
+ * @param objectName 存储桶里的对象名称
+ * @param expires 失效时间(以秒为单位),默认是7天,不得大于七天
+ * @return
+ */
+ @SneakyThrows
+ public String presignedPutObject(String bucketName, String objectName, Integer expires) {
+ boolean flag = bucketExists(bucketName);
+ String url = "";
+ if (flag) {
+ if (expires < 1 || expires > DEFAULT_EXPIRY_TIME) {
+ throw new InvalidExpiresRangeException(expires,
+ "expires must be in range of 1 to " + DEFAULT_EXPIRY_TIME);
+ }
+ url = minioClient.presignedPutObject(bucketName, objectName, expires);
+ }
+ return url;
+ }
+
+ /**
+ * 获取对象的元数据
+ *
+ * @param bucketName 存储桶名称
+ * @param objectName 存储桶里的对象名称
+ * @return
+ */
+ @SneakyThrows
+ public ObjectStat statObject(String bucketName, String objectName) {
+ boolean flag = bucketExists(bucketName);
+ if (flag) {
+ ObjectStat statObject = minioClient.statObject(bucketName, objectName);
+ return statObject;
+ }
+ return null;
+ }
+
+ /**
+ * 文件访问路径
+ *
+ * @param bucketName 存储桶名称
+ * @param objectName 存储桶里的对象名称
+ * @return
+ */
+ @SneakyThrows
+ public String getObjectUrl(String bucketName, String objectName) {
+ boolean flag = bucketExists(bucketName);
+ String url = "";
+ if (flag) {
+ url = minioClient.getObjectUrl(bucketName, objectName);
+ }
+ return url;
+ }
+
+
+
+ public void downloadFile(String bucketName, String fileName, String originalName, HttpServletResponse response) {
+ try {
+
+ InputStream file = minioClient.getObject(bucketName, fileName);
+ String filename = new String(fileName.getBytes("ISO8859-1"), StandardCharsets.UTF_8);
+ if (StringUtils.isNotEmpty(originalName)) {
+ fileName = originalName;
+ }
+ response.setHeader("Content-Disposition", "attachment;filename=" + filename);
+ ServletOutputStream servletOutputStream = response.getOutputStream();
+ int len;
+ byte[] buffer = new byte[1024];
+ while ((len = file.read(buffer)) > 0) {
+ servletOutputStream.write(buffer, 0, len);
+ }
+ servletOutputStream.flush();
+ file.close();
+ servletOutputStream.close();
+ } catch (ErrorResponseException e) {
+ e.printStackTrace();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/itools-fms/itools-fms-model/pom.xml b/itools-fms/itools-fms-model/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f7be9ab8fa10a0a0e5ef12a223e814b10a793bf4
--- /dev/null
+++ b/itools-fms/itools-fms-model/pom.xml
@@ -0,0 +1,33 @@
+
+
+
+ itools-fms
+ com.itools.core
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ itools-fms-model
+
+
+
+ com.baomidou
+ mybatis-plus-boot-starter
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+ com.baomidou
+ mybatis-plus-generator
+
+
+ org.projectlombok
+ lombok
+
+
+
+
\ No newline at end of file
diff --git a/itools-fms/itools-fms-model/src/main/java/com/itools/core/dto/accessToken/FmsAccessTokenDTO.java b/itools-fms/itools-fms-model/src/main/java/com/itools/core/dto/accessToken/FmsAccessTokenDTO.java
new file mode 100644
index 0000000000000000000000000000000000000000..ada12f03f8a82c48a0993c79b8f1916431f1e800
--- /dev/null
+++ b/itools-fms/itools-fms-model/src/main/java/com/itools/core/dto/accessToken/FmsAccessTokenDTO.java
@@ -0,0 +1,28 @@
+package com.itools.core.dto.accessToken;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+/**
+ * @project: itools-backend
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-03-28 15:51
+ */
+@Data
+@TableName("itools_fms_access_token")
+public final class FmsAccessTokenDTO {
+ /**
+ * 文件访问token
+ */
+ private String fileAccessToken;
+ /**
+ * 文件的唯一id
+ */
+ private String uniqueId;
+ /**
+ * 访问类型:show或者download
+ */
+ private String type;
+
+}
diff --git a/itools-fms/itools-fms-model/src/main/java/com/itools/core/dto/businessType/FmsBusinessTypeDTO.java b/itools-fms/itools-fms-model/src/main/java/com/itools/core/dto/businessType/FmsBusinessTypeDTO.java
new file mode 100644
index 0000000000000000000000000000000000000000..9a0ff7923a590bf84a8d2546b727da6e7ffde612
--- /dev/null
+++ b/itools-fms/itools-fms-model/src/main/java/com/itools/core/dto/businessType/FmsBusinessTypeDTO.java
@@ -0,0 +1,52 @@
+package com.itools.core.dto.businessType;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @project: itools-backend
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-03-28 15:51
+ */
+@Data
+@TableName("itools_fms_business_type")
+public class FmsBusinessTypeDTO {
+ /**
+ * 主键
+ */
+ private Long id;
+
+ /**
+ * 业务类型
+ */
+ private String businessType;
+
+ /**
+ * 说明
+ */
+ private String remark;
+
+ /**
+ * 文件大小, 单位kb
+ */
+ private String fsSize;
+
+ /**
+ * 文件类型,逗号分隔符,例如: jpg,png
+ */
+ private String fsType;
+
+ /**
+ * 创建时间
+ */
+ private Date createDate;
+
+ /**
+ * 更新时间
+ */
+ private Date updateDate;
+
+}
\ No newline at end of file
diff --git a/itools-fms/itools-fms-model/src/main/java/com/itools/core/dto/fileRecord/FmsRecordDTO.java b/itools-fms/itools-fms-model/src/main/java/com/itools/core/dto/fileRecord/FmsRecordDTO.java
new file mode 100644
index 0000000000000000000000000000000000000000..cc3932d1ff5b478eeaea763f1eae0134cb0c211c
--- /dev/null
+++ b/itools-fms/itools-fms-model/src/main/java/com/itools/core/dto/fileRecord/FmsRecordDTO.java
@@ -0,0 +1,77 @@
+package com.itools.core.dto.fileRecord;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.util.Date;
+import java.util.List;
+/**
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-03-28 15:51
+ */
+@Data
+@TableName("itools_fms_record")
+public class FmsRecordDTO {
+ /**
+ * 主键
+ */
+ private Long id;
+
+ /**
+ * HTTP协议定义的文件类型,文件上传从文件流中获取
+ * 文件存取时使用该字段填入response的content-type字段
+ */
+ private String contentType;
+
+ /**
+ * 文件所属系统,文件上传时指定
+ */
+ private String fromSystemId;
+
+ /**
+ * 文件大小,单位为字节
+ */
+ private Long fileSize;
+
+ /**
+ * 文件的全局唯一ID,后续访问均使用该ID
+ */
+ private String uniqueId;
+ /**
+ * 文件的全局唯一IDs,后续访问均使用该IDs
+ */
+ private List uniqueIds;
+
+ /**
+ * 文件描述信息
+ */
+ private String remark;
+
+ /**
+ * 原文件名,来自入参
+ */
+ private String origFileName;
+
+ /**
+ * 创建时间
+ */
+ private Date createTime;
+
+ /**
+ * 更新时间
+ */
+ private Date updateTime;
+
+ /**
+ * 删除时间
+ */
+ private Date deleteTime;
+
+ /**
+ * 是否已删除文件本身,也即是说,删除文件时数据库记录仅仅将该字段置位1,并不实际删除数据库记录
+ * 0:没有删除
+ * 1:已删除
+ */
+ private String deleted;
+}
\ No newline at end of file
diff --git a/itools-fms/itools-fms-model/src/main/java/com/itools/core/param/FmsAccessTokenParam.java b/itools-fms/itools-fms-model/src/main/java/com/itools/core/param/FmsAccessTokenParam.java
new file mode 100644
index 0000000000000000000000000000000000000000..01f4a848076de84859efb24c4b66d120c8a574ba
--- /dev/null
+++ b/itools-fms/itools-fms-model/src/main/java/com/itools/core/param/FmsAccessTokenParam.java
@@ -0,0 +1,69 @@
+package com.itools.core.param;
+
+
+/**
+ * @project: itools-backend
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-03-28 15:51
+ */
+public class FmsAccessTokenParam {
+ /**
+ * 有效时长
+ */
+ private int expiredTime;
+
+ /**
+ * 最大访问次数
+ */
+ private int maxAccessCount;
+
+ /**
+ * 文件访问唯一id
+ */
+ private String uniqueId;
+
+ private String type;
+
+ public FmsAccessTokenParam(int expiredTime, int maxAccessCount, String uniqueId, String type) {
+ this.expiredTime = expiredTime;
+ this.maxAccessCount = maxAccessCount;
+ this.uniqueId = uniqueId;
+ this.type = type;
+ }
+
+ public FmsAccessTokenParam() {
+ }
+
+ public int getExpiredTime() {
+ return expiredTime;
+ }
+
+ public void setExpiredTime(int expiredTime) {
+ this.expiredTime = expiredTime;
+ }
+
+ public int getMaxAccessCount() {
+ return maxAccessCount;
+ }
+
+ public void setMaxAccessCount(int maxAccessCount) {
+ this.maxAccessCount = maxAccessCount;
+ }
+
+ public String getUniqueId() {
+ return uniqueId;
+ }
+
+ public void setUniqueId(String uniqueId) {
+ this.uniqueId = uniqueId;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+}
diff --git a/itools-fms/itools-fms-model/src/main/java/com/itools/core/param/FmsBusinessTypeParam.java b/itools-fms/itools-fms-model/src/main/java/com/itools/core/param/FmsBusinessTypeParam.java
new file mode 100644
index 0000000000000000000000000000000000000000..209597469c8edca3ad2d81a4e9017c5e48c6863c
--- /dev/null
+++ b/itools-fms/itools-fms-model/src/main/java/com/itools/core/param/FmsBusinessTypeParam.java
@@ -0,0 +1,102 @@
+package com.itools.core.param;
+
+import java.util.Date;
+
+/**
+ * @project: itools-backend
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-03-28 15:51
+ */
+public class FmsBusinessTypeParam {
+ /**
+ * 主键
+ */
+ private Long id;
+
+ /**
+ * 业务类型
+ */
+ private String businessType;
+
+ /**
+ * 说明
+ */
+ private String remark;
+
+ /**
+ * 文件大小, 单位kb
+ */
+ private String fsSize;
+
+ /**
+ * 文件类型,逗号分隔符,例如: jpg,png
+ */
+ private String fsType;
+
+ /**
+ * 创建时间
+ */
+ private Date createDate;
+
+ /**
+ * 更新时间
+ */
+ private Date updateDate;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getBusinessType() {
+ return businessType;
+ }
+
+ public void setBusinessType(String businessType) {
+ this.businessType = businessType;
+ }
+
+ public String getRemark() {
+ return remark;
+ }
+
+ public void setRemark(String remark) {
+ this.remark = remark;
+ }
+
+ public String getFsSize() {
+ return fsSize;
+ }
+
+ public void setFsSize(String fsSize) {
+ this.fsSize = fsSize;
+ }
+
+ public String getFsType() {
+ return fsType;
+ }
+
+ public void setFsType(String fsType) {
+ this.fsType = fsType;
+ }
+
+ public Date getCreateDate() {
+ return createDate;
+ }
+
+ public void setCreateDate(Date createDate) {
+ this.createDate = createDate;
+ }
+
+ public Date getUpdateDate() {
+ return updateDate;
+ }
+
+ public void setUpdateDate(Date updateDate) {
+ this.updateDate = updateDate;
+ }
+}
\ No newline at end of file
diff --git a/itools-fms/itools-fms-model/src/main/java/com/itools/core/param/FmsUploadTokenParam.java b/itools-fms/itools-fms-model/src/main/java/com/itools/core/param/FmsUploadTokenParam.java
new file mode 100644
index 0000000000000000000000000000000000000000..fb5b2c4e418f53ef6f3164fecfe408df2c7cf120
--- /dev/null
+++ b/itools-fms/itools-fms-model/src/main/java/com/itools/core/param/FmsUploadTokenParam.java
@@ -0,0 +1,58 @@
+package com.itools.core.param;
+
+import com.itools.core.result.FmsBusinessTypeResult;
+
+/**
+ * @project: itools-backend
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-03-28 15:51
+ */
+public class FmsUploadTokenParam {
+
+ private FmsBusinessTypeResult fsBusinessType;
+ private String fromSystemId;
+ private String needEncrypt;
+ private String remark;
+ private String originalFilename;
+
+ public FmsBusinessTypeResult getFsBusinessType() {
+ return fsBusinessType;
+ }
+
+ public void setFsBusinessType(FmsBusinessTypeResult fsBusinessType) {
+ this.fsBusinessType = fsBusinessType;
+ }
+
+ public String getFromSystemId() {
+ return fromSystemId;
+ }
+
+ public void setFromSystemId(String fromSystemId) {
+ this.fromSystemId = fromSystemId;
+ }
+
+ public String getNeedEncrypt() {
+ return needEncrypt;
+ }
+
+ public void setNeedEncrypt(String needEncrypt) {
+ this.needEncrypt = needEncrypt;
+ }
+
+ public String getRemark() {
+ return remark;
+ }
+
+ public void setRemark(String remark) {
+ this.remark = remark;
+ }
+
+ public String getOriginalFilename() {
+ return originalFilename;
+ }
+
+ public void setOriginalFilename(String originalFilename) {
+ this.originalFilename = originalFilename;
+ }
+}
diff --git a/itools-fms/itools-fms-model/src/main/java/com/itools/core/request/FmsBase64FileUploadRequest.java b/itools-fms/itools-fms-model/src/main/java/com/itools/core/request/FmsBase64FileUploadRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..42ac3265b99d833fa5590324ca603f1e6b76dbd8
--- /dev/null
+++ b/itools-fms/itools-fms-model/src/main/java/com/itools/core/request/FmsBase64FileUploadRequest.java
@@ -0,0 +1,55 @@
+package com.itools.core.request;
+
+/**
+ * @project: itools-backend
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-03-28 15:51
+ */
+public class FmsBase64FileUploadRequest {
+
+ String fileBaseSixFour;
+ String fileName;
+ String businessType;
+ String uploadToken;
+
+ public String getFileBaseSixFour() {
+ return fileBaseSixFour;
+ }
+
+
+ public void setFileBaseSixFour(String fileBaseSixFour) {
+ this.fileBaseSixFour = fileBaseSixFour;
+ }
+
+
+ public String getFileName() {
+ return fileName;
+ }
+
+
+ public void setFileName(String fileName) {
+ this.fileName = fileName;
+ }
+
+
+ public String getBusinessType() {
+ return businessType;
+ }
+
+
+ public void setBusinessType(String businessType) {
+ this.businessType = businessType;
+ }
+
+
+ public String getUploadToken() {
+ return uploadToken;
+ }
+
+
+ public void setUploadToken(String uploadToken) {
+ this.uploadToken = uploadToken;
+ }
+
+}
diff --git a/itools-fms/itools-fms-model/src/main/java/com/itools/core/request/FmsFileAccessUrlRequest.java b/itools-fms/itools-fms-model/src/main/java/com/itools/core/request/FmsFileAccessUrlRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..6f06b4fdd27b19ea2ab72374e9ef2d2e42cbf0f5
--- /dev/null
+++ b/itools-fms/itools-fms-model/src/main/java/com/itools/core/request/FmsFileAccessUrlRequest.java
@@ -0,0 +1,51 @@
+package com.itools.core.request;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @Author XUCHANG
+ * @description:
+ * @Date 2020/11/5 13:46
+ */
+public class FmsFileAccessUrlRequest implements Serializable {
+ private List uniqueIds;
+ private Integer expiredTime;
+ private Integer maxAccessCount;
+ private String type;
+
+ public FmsFileAccessUrlRequest() {
+ }
+
+ public List getUniqueIds() {
+ return uniqueIds;
+ }
+
+ public void setUniqueIds(List uniqueIds) {
+ this.uniqueIds = uniqueIds;
+ }
+
+ public Integer getExpiredTime() {
+ return expiredTime;
+ }
+
+ public void setExpiredTime(Integer expiredTime) {
+ this.expiredTime = expiredTime;
+ }
+
+ public Integer getMaxAccessCount() {
+ return maxAccessCount;
+ }
+
+ public void setMaxAccessCount(Integer maxAccessCount) {
+ this.maxAccessCount = maxAccessCount;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+}
diff --git a/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsAccessTokenResult.java b/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsAccessTokenResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..0eb4450aa99264db05e17c0a8f3d497ad1e1fbe8
--- /dev/null
+++ b/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsAccessTokenResult.java
@@ -0,0 +1,67 @@
+package com.itools.core.result;
+
+/**
+ * @Author XUCHANG
+ * @description:
+ * @Date 2020/11/5 14:35
+ */
+public class FmsAccessTokenResult {
+ /**
+ * 有效时长
+ */
+ private int expiredTime;
+
+ /**
+ * 最大访问次数
+ */
+ private int maxAccessCount;
+
+ /**
+ * 文件访问唯一id
+ */
+ private String uniqueId;
+
+ private String type;
+
+ public FmsAccessTokenResult(int expiredTime, int maxAccessCount, String uniqueId, String type) {
+ this.expiredTime = expiredTime;
+ this.maxAccessCount = maxAccessCount;
+ this.uniqueId = uniqueId;
+ this.type = type;
+ }
+
+ public FmsAccessTokenResult() {
+ }
+
+ public int getExpiredTime() {
+ return expiredTime;
+ }
+
+ public void setExpiredTime(int expiredTime) {
+ this.expiredTime = expiredTime;
+ }
+
+ public int getMaxAccessCount() {
+ return maxAccessCount;
+ }
+
+ public void setMaxAccessCount(int maxAccessCount) {
+ this.maxAccessCount = maxAccessCount;
+ }
+
+ public String getUniqueId() {
+ return uniqueId;
+ }
+
+ public void setUniqueId(String uniqueId) {
+ this.uniqueId = uniqueId;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+}
diff --git a/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsBusinessTypeResult.java b/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsBusinessTypeResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..b1a65469b7e5410ea3bf396aad6aa4a19d919914
--- /dev/null
+++ b/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsBusinessTypeResult.java
@@ -0,0 +1,104 @@
+package com.itools.core.result;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @Author XUCHANG
+ * @description:
+ * @Date 2020/11/5 14:35
+ */
+public class FmsBusinessTypeResult implements Serializable {
+
+ private static final long serialVersionUID = -5246507559164483529L;
+ /**
+ * 主键
+ */
+ private Long id;
+
+ /**
+ * 业务类型
+ */
+ private String businessType;
+
+ /**
+ * 说明
+ */
+ private String remark;
+
+ /**
+ * 文件大小, 单位kb
+ */
+ private String fsSize;
+
+ /**
+ * 文件类型,逗号分隔符,例如: jpg,png
+ */
+ private String fsType;
+
+ /**
+ * 创建时间
+ */
+ private Date createDate;
+
+ /**
+ * 更新时间
+ */
+ private Date updateDate;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getBusinessType() {
+ return businessType;
+ }
+
+ public void setBusinessType(String businessType) {
+ this.businessType = businessType;
+ }
+
+ public String getRemark() {
+ return remark;
+ }
+
+ public void setRemark(String remark) {
+ this.remark = remark;
+ }
+
+ public String getFsSize() {
+ return fsSize;
+ }
+
+ public void setFsSize(String fsSize) {
+ this.fsSize = fsSize;
+ }
+
+ public String getFsType() {
+ return fsType;
+ }
+
+ public void setFsType(String fsType) {
+ this.fsType = fsType;
+ }
+
+ public Date getCreateDate() {
+ return createDate;
+ }
+
+ public void setCreateDate(Date createDate) {
+ this.createDate = createDate;
+ }
+
+ public Date getUpdateDate() {
+ return updateDate;
+ }
+
+ public void setUpdateDate(Date updateDate) {
+ this.updateDate = updateDate;
+ }
+}
\ No newline at end of file
diff --git a/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsDetailRecordResult.java b/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsDetailRecordResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..cb29afe06f246700fb5978f7584ccc718c7a6ca2
--- /dev/null
+++ b/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsDetailRecordResult.java
@@ -0,0 +1,156 @@
+package com.itools.core.result;
+
+import java.util.Date;
+
+/**
+ * @Author XUCHANG
+ * @description:
+ * @Date 2020/11/4 18:01
+ */
+public class FmsDetailRecordResult {
+ /**
+ * 主键
+ */
+ private Long id;
+
+ /**
+ * HTTP协议定义的文件类型,文件上传从文件流中获取
+ * 文件存取时使用该字段填入response的content-type字段
+ */
+ private String contentType;
+
+ /**
+ * 文件所属系统,文件上传时指定
+ */
+ private String fromSystemId;
+
+ /**
+ * 文件大小,单位为字节
+ */
+ private Long fileSize;
+
+ /**
+ * 文件的全局唯一ID,后续访问均使用该ID
+ */
+ private String uniqueId;
+
+ /**
+ * 文件描述信息
+ */
+ private String remark;
+
+ /**
+ * 原文件名,来自入参
+ */
+ private String origFileName;
+
+ /**
+ * 创建时间
+ */
+ private Date createTime;
+
+ /**
+ * 更新时间
+ */
+ private Date updateTime;
+
+ /**
+ * 删除时间
+ */
+ private Date deleteTime;
+
+ /**
+ * 是否已删除文件本身,也即是说,删除文件时数据库记录仅仅将该字段置位1,并不实际删除数据库记录
+ * 0:没有删除
+ * 1:已删除
+ */
+ private String deleted;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getContentType() {
+ return contentType;
+ }
+
+ public void setContentType(String contentType) {
+ this.contentType = contentType;
+ }
+
+ public String getFromSystemId() {
+ return fromSystemId;
+ }
+
+ public void setFromSystemId(String fromSystemId) {
+ this.fromSystemId = fromSystemId;
+ }
+
+ public Long getFileSize() {
+ return fileSize;
+ }
+
+ public void setFileSize(Long fileSize) {
+ this.fileSize = fileSize;
+ }
+
+ public String getUniqueId() {
+ return uniqueId;
+ }
+
+ public void setUniqueId(String uniqueId) {
+ this.uniqueId = uniqueId;
+ }
+
+ public String getRemark() {
+ return remark;
+ }
+
+ public void setRemark(String remark) {
+ this.remark = remark;
+ }
+
+ public String getOrigFileName() {
+ return origFileName;
+ }
+
+ public void setOrigFileName(String origFileName) {
+ this.origFileName = origFileName;
+ }
+
+ public Date getCreateTime() {
+ return createTime;
+ }
+
+ public void setCreateTime(Date createTime) {
+ this.createTime = createTime;
+ }
+
+ public Date getUpdateTime() {
+ return updateTime;
+ }
+
+ public void setUpdateTime(Date updateTime) {
+ this.updateTime = updateTime;
+ }
+
+ public Date getDeleteTime() {
+ return deleteTime;
+ }
+
+ public void setDeleteTime(Date deleteTime) {
+ this.deleteTime = deleteTime;
+ }
+
+ public String getDeleted() {
+ return deleted;
+ }
+
+ public void setDeleted(String deleted) {
+ this.deleted = deleted;
+ }
+}
\ No newline at end of file
diff --git a/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsFileRecordPathResult.java b/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsFileRecordPathResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..18b04c685136c95e141c5d79dcc1f0d5166514d1
--- /dev/null
+++ b/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsFileRecordPathResult.java
@@ -0,0 +1,32 @@
+package com.itools.core.result;
+
+import java.io.Serializable;
+
+/**
+ * @Author XUCHANG
+ * @description:
+ * @Date 2020/11/5 14:35
+ */
+public class FmsFileRecordPathResult implements Serializable {
+ /**
+ * 文件访问唯一id
+ */
+ private String uniqueId;
+ private String path;
+
+ public String getUniqueId() {
+ return uniqueId;
+ }
+
+ public void setUniqueId(String uniqueId) {
+ this.uniqueId = uniqueId;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+}
diff --git a/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsFileUploadResult.java b/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsFileUploadResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..675c01835bb920501e6322cc994eab0ef6dff9c5
--- /dev/null
+++ b/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsFileUploadResult.java
@@ -0,0 +1,21 @@
+package com.itools.core.result;
+
+/**
+ * @Author XUCHANG
+ * @description:
+ * @Date 2020/11/5 14:35
+ */
+public class FmsFileUploadResult {
+ /**
+ * 成功时必填,该文件的唯一ID
+ */
+ private String uniqueId;
+
+ public String getUniqueId() {
+ return uniqueId;
+ }
+
+ public void setUniqueId(String uniqueId) {
+ this.uniqueId = uniqueId;
+ }
+}
diff --git a/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsMultipartFileResult.java b/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsMultipartFileResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..9d6b560c4c8f4fa03e3c3c12c3db60411760265d
--- /dev/null
+++ b/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsMultipartFileResult.java
@@ -0,0 +1,35 @@
+package com.itools.core.result;
+
+import java.io.Serializable;
+
+/**
+ * @Author XUCHANG
+ * @description:
+ * @Date 2020/11/4 18:01
+ */
+public class FmsMultipartFileResult implements Serializable {
+ /**
+ * 文件访问唯一id
+ */
+ private String uniqueId;
+ /**
+ * 文件名称
+ */
+ private String fileName;
+
+ public String getUniqueId() {
+ return uniqueId;
+ }
+
+ public void setUniqueId(String uniqueId) {
+ this.uniqueId = uniqueId;
+ }
+
+ public String getFileName() {
+ return fileName;
+ }
+
+ public void setFileName(String fileName) {
+ this.fileName = fileName;
+ }
+}
diff --git a/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsRecordResult.java b/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsRecordResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..470226e692f505c8578a45bd32df402e6b48af3d
--- /dev/null
+++ b/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsRecordResult.java
@@ -0,0 +1,20 @@
+package com.itools.core.result;
+
+/**
+ * @Author XUCHANG
+ * @description:
+ * @Date 2020/11/4 18:01
+ */
+public class FmsRecordResult {
+
+ private FmsDetailRecordResult fssRecord;
+
+ public FmsDetailRecordResult getFssRecord() {
+ return fssRecord;
+ }
+
+ public void setFssRecord(FmsDetailRecordResult fssRecord) {
+ this.fssRecord = fssRecord;
+ }
+
+}
diff --git a/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsUploadTokenResult.java b/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsUploadTokenResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..2eb7f12fde6012ae68a6554981c0d9bbc958841d
--- /dev/null
+++ b/itools-fms/itools-fms-model/src/main/java/com/itools/core/result/FmsUploadTokenResult.java
@@ -0,0 +1,49 @@
+package com.itools.core.result;
+
+import java.io.Serializable;
+
+/**
+ * @Author XUCHANG
+ * @description:
+ * @Date 2020/11/4 18:01
+ */
+public class FmsUploadTokenResult implements Serializable {
+
+ private FmsBusinessTypeResult fsBusinessType;
+
+ private String fromSystemId;
+ private String needEncrypt;
+ private String remark;
+
+ public FmsBusinessTypeResult getFsBusinessType() {
+ return fsBusinessType;
+ }
+
+ public void setFsBusinessType(FmsBusinessTypeResult fsBusinessType) {
+ this.fsBusinessType = fsBusinessType;
+ }
+
+ public String getFromSystemId() {
+ return fromSystemId;
+ }
+
+ public void setFromSystemId(String fromSystemId) {
+ this.fromSystemId = fromSystemId;
+ }
+
+ public String getNeedEncrypt() {
+ return needEncrypt;
+ }
+
+ public void setNeedEncrypt(String needEncrypt) {
+ this.needEncrypt = needEncrypt;
+ }
+
+ public String getRemark() {
+ return remark;
+ }
+
+ public void setRemark(String remark) {
+ this.remark = remark;
+ }
+}
diff --git a/itools-fms/itools-fms-server/pom.xml b/itools-fms/itools-fms-server/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9c509107e9d8af9492bce0cd16c691fa1af9790d
--- /dev/null
+++ b/itools-fms/itools-fms-server/pom.xml
@@ -0,0 +1,90 @@
+
+
+
+ itools-fms
+ com.itools.core
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ itools-fms-server
+
+
+ com.itools.core
+ itools-fms-core
+ 1.0-SNAPSHOT
+
+
+ com.itools.core
+ itools-fms-model
+ 1.0-SNAPSHOT
+
+
+ com.itools.core
+ itools-common
+ 1.0-SNAPSHOT
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-discovery
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-config
+
+
+ org.projectlombok
+ lombok
+
+
+ com.baomidou
+ mybatis-plus-boot-starter
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+ com.baomidou
+ mybatis-plus-generator
+
+
+
+ mysql
+ mysql-connector-java
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+ org.apache.commons
+ commons-pool2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/itools-fms/itools-fms-server/src/main/java/com/itools/core/FileSystemApplication.java b/itools-fms/itools-fms-server/src/main/java/com/itools/core/FileSystemApplication.java
new file mode 100644
index 0000000000000000000000000000000000000000..d19c47834b18cde23968ead5e8a32d6a260bd434
--- /dev/null
+++ b/itools-fms/itools-fms-server/src/main/java/com/itools/core/FileSystemApplication.java
@@ -0,0 +1,54 @@
+package com.itools.core;
+
+import com.itools.core.snowflake.config.EnableSequenceService;
+import com.itools.core.validate.EnableValidator;
+import lombok.extern.log4j.Log4j2;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.Banner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-03-28 15:51
+ */
+@SpringBootApplication
+@EnableSequenceService
+@EnableValidator
+@MapperScan("com.itools.core.mapper")
+public class FileSystemApplication {
+ public static void main(String[] args) {
+ SpringApplication springApplication = new SpringApplication(FileSystemApplication.class);
+ springApplication.setBannerMode(Banner.Mode.OFF);
+ springApplication.run(args);
+ }
+ @Bean
+ public CorsFilter corsFilter() {
+ final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ final CorsConfiguration config = new CorsConfiguration();
+ // 允许cookies跨域
+ config.setAllowCredentials(true);
+ // 允许向该服务器提交请求的URI,*表示全部允许。。这里尽量限制来源域,比如http://xxxx:8080 ,以降低安全风险。。
+ config.addAllowedOrigin("*");
+ // 允许访问的头信息,*表示全部
+ config.addAllowedHeader("*");
+ // 预检请求的缓存时间(秒),即在这个时间段里,对于相同的跨域请求不会再预检了
+ config.setMaxAge(18000L);
+ // 允许提交请求的方法,*表示全部允许,也可以单独设置GET、PUT等
+ config.addAllowedMethod("*");
+ config.addAllowedMethod("HEAD");
+ // 允许Get的请求方法
+ config.addAllowedMethod("GET");
+ config.addAllowedMethod("PUT");
+ config.addAllowedMethod("POST");
+ config.addAllowedMethod("DELETE");
+ config.addAllowedMethod("PATCH");
+ source.registerCorsConfiguration("/**", config);
+ return new CorsFilter(source);
+ }
+}
diff --git a/itools-fms/itools-fms-server/src/main/java/com/itools/core/controller/FmsFileRecordController.java b/itools-fms/itools-fms-server/src/main/java/com/itools/core/controller/FmsFileRecordController.java
new file mode 100644
index 0000000000000000000000000000000000000000..0ad6405bded3208a709bb8816808385a177caa4b
--- /dev/null
+++ b/itools-fms/itools-fms-server/src/main/java/com/itools/core/controller/FmsFileRecordController.java
@@ -0,0 +1,44 @@
+package com.itools.core.controller;
+
+
+import com.itools.core.base.CommonResult;
+import com.itools.core.log.Logable;
+import com.itools.core.result.FmsRecordResult;
+import com.itools.core.result.FmsDetailRecordResult;
+import com.itools.core.service.FmsRecordService;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.io.IOException;
+
+/**
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-04-01 11:26
+ */
+@RestController
+@ApiOperation("FmsFileRecordController")
+public class FmsFileRecordController {
+
+ @Autowired
+ private FmsRecordService fmsRecordService;
+
+ /**
+ * 获取文件记录信息 (内部调用)
+ * @return
+ * @throws IOException
+ */
+ @RequestMapping(value = "/fssRecord", method = RequestMethod.GET)
+ @Logable
+ @ApiOperation(value = "获取文件记录信息", notes = "获取文件记录信息", httpMethod = "GET")
+ public CommonResult queryFssRecordByUniqueId(@RequestParam("uniqueId") String uniqueId) {
+ FmsRecordResult response = new FmsRecordResult();
+ FmsDetailRecordResult record = fmsRecordService.queryFssRecordByUniqueId(uniqueId);
+ response.setFssRecord(record);
+ return CommonResult.success(response);
+ }
+}
diff --git a/itools-fms/itools-fms-server/src/main/java/com/itools/core/controller/FmsFileSystemController.java b/itools-fms/itools-fms-server/src/main/java/com/itools/core/controller/FmsFileSystemController.java
new file mode 100644
index 0000000000000000000000000000000000000000..1750651794168d23eacec1a92d9a53032badcfcb
--- /dev/null
+++ b/itools-fms/itools-fms-server/src/main/java/com/itools/core/controller/FmsFileSystemController.java
@@ -0,0 +1,313 @@
+package com.itools.core.controller;
+
+import com.itools.core.base.CommonResult;
+import com.itools.core.em.FmsCodeBean;
+import com.itools.core.exception.AppException;
+import com.itools.core.log.Logable;
+import com.itools.core.param.FmsAccessTokenParam;
+import com.itools.core.param.FmsUploadTokenParam;
+import com.itools.core.param.FmsBusinessTypeParam;
+import com.itools.core.request.FmsBase64FileUploadRequest;
+import com.itools.core.result.*;
+import com.itools.core.service.FmsAccessTokenService;
+import com.itools.core.service.FmsBusinessTypeService;
+import com.itools.core.service.FmsFileSystemService;
+import com.itools.core.utils.Base64Utils;
+import com.itools.core.utils.StringUtils;
+import com.itools.core.utils.ZipUtils;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.FileCopyUtils;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+import sun.misc.BASE64Encoder;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.List;
+/**
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-04-01 11:26
+ */
+@RestController
+@ApiOperation("FmsFileSystemController")
+public class FmsFileSystemController {
+
+ @Autowired
+ private FmsBusinessTypeService fmsBusinessTypeService;
+
+ @Autowired
+ private FmsAccessTokenService fmsAccessTokenService;
+
+ @Autowired
+ private FmsFileSystemService fmsFileSystemService;
+
+ private static final String SHOW = "show";
+
+ private static final String DOWNLOAD = "download";
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(FmsFileSystemController.class);
+
+ @PostMapping("FilePath")
+ @Logable
+ @ApiOperation(value = "获取文件访问路径", notes = "获取文件访问路径", httpMethod = "POST")
+ @ApiImplicitParams({
+ @ApiImplicitParam(name = "uniqueId", value = "文件的唯一ID", required = true, dataType = "String", paramType = "query"),
+ @ApiImplicitParam(name = "expiredTime", value = "有效时长,单位分钟", required = true, dataType = "Long", paramType = "query"),
+ @ApiImplicitParam(name = "maxAccessCount", value = "最大访问次数", required = false, dataType = "Long", paramType = "query"),
+ @ApiImplicitParam(name = "type", value = "文件下载 download/展示 show", required = true, dataType = "String", paramType = "query")
+ })
+ public CommonResult getFileAccessUrl(String uniqueId, Integer expiredTime, @RequestParam(defaultValue = "-1", required = false) int maxAccessCount, String type) {
+ String fileUrlByFileId = fmsFileSystemService.getFileUrlByFileId(uniqueId, expiredTime, maxAccessCount, type);
+ return CommonResult.success(fileUrlByFileId);
+ }
+
+ @PostMapping("FilesPath")
+ @Logable
+ @ApiOperation(value = "获取文件访问路径", notes = "获取文件访问路径", httpMethod = "POST")
+ @ApiImplicitParams({
+ @ApiImplicitParam(name = "uniqueIds", value = "文件的唯一IDS数组", required = true, dataType = "String", paramType = "query"),
+ @ApiImplicitParam(name = "expiredTime", value = "有效时长,单位分钟", required = true, dataType = "Long", paramType = "query"),
+ @ApiImplicitParam(name = "maxAccessCount", value = "最大访问次数", required = false, dataType = "Long", paramType = "query"),
+ @ApiImplicitParam(name = "type", value = "文件下载 download/展示 show", required = true, dataType = "String", paramType = "query")
+ })
+ public CommonResult getFileAccessUrl(@RequestParam(value = "uniqueIds",required = false) List uniqueIds,
+ @RequestParam(value = "expiredTime",required = false) Integer expiredTime,
+ @RequestParam(value = "maxAccessCount",defaultValue = "-1", required = false) Integer maxAccessCount,
+ @RequestParam(value = "type",required = false) String type) {
+ return fmsFileSystemService.getFileUrlByFileIds(uniqueIds, expiredTime, maxAccessCount, type);
+ }
+
+ /**
+ * 仅内部微服务使用,不应该对外开放
+ * @param businessType
+ * @param fromSystemId
+ * @param needEncrypt
+ * @param remark
+ * @return
+ */
+ @PostMapping("UploadToken")
+ @Logable
+ @ApiOperation(value = "申请文件上传token", notes = "申请文件上传token", httpMethod = "POST")
+ @ApiImplicitParams({
+ @ApiImplicitParam(name = "businessType", value = "文件类型", required = true, dataType = "String", paramType = "query"),
+ @ApiImplicitParam(name = "fromSystemId", value = "上传的文件来自哪个子系统,系统编号", required = true, dataType = "String", paramType = "query"),
+ @ApiImplicitParam(name = "needEncrypt", value = "是否需加密,后续扩展使用,本期不使用,默认否.0:否 1:是", required = false, dataType = "String", paramType = "query"),
+ @ApiImplicitParam(name = "remark", value = "文件描述信息", required = false, dataType = "String", paramType = "query")
+ })
+ public CommonResult applyUploadToken(String businessType, String fromSystemId, @RequestParam(required = false, defaultValue = "0") String needEncrypt, String remark) {
+ String uploadToken = fmsFileSystemService.applyUploadToken(businessType, fromSystemId, needEncrypt, remark);
+ return CommonResult.success(uploadToken);
+ }
+
+ @GetMapping("File/{uniqueId}")
+ @Logable
+ public void downloadFile(@PathVariable String uniqueId, @RequestParam("fileAccessToken") String fileAccessToken, HttpServletResponse response) {
+ try {
+ FmsAccessTokenResult fsAccessToken = fmsAccessTokenService.getFileAccessToken(fileAccessToken);
+ if (fsAccessToken == null) {
+ throw new AppException(FmsCodeBean.FmsCode.INVALID_FS_TOKEN.code);
+ }
+ if (!uniqueId.equals(fsAccessToken.getUniqueId())) {
+ throw new AppException(FmsCodeBean.FmsCode.NOT_EXIST_FILE.code);
+ }
+ FmsAccessTokenParam param = new FmsAccessTokenParam();
+ BeanUtils.copyProperties(fsAccessToken , param);
+ FmsDetailRecordResult fsUploadRecord = fmsFileSystemService.getFileUploadRecord(param, uniqueId, fileAccessToken);
+ String type = fsAccessToken.getType();
+ if (SHOW.equals(type)) {
+ response.addHeader("Content-Length", "" + fsUploadRecord.getFileSize());
+ } else if (DOWNLOAD.equals(type)) {
+ // 设置文件名, 可用于下载
+ response.addHeader("Content-Length", "" + fsUploadRecord.getFileSize());
+ response.addHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(fsUploadRecord.getOrigFileName(), "utf-8"));
+ }
+ response.setCharacterEncoding("UTF-8");
+ response.setContentType(fsUploadRecord.getContentType());
+ OutputStream outputStream = response.getOutputStream();
+ FileCopyUtils.copy(new FileInputStream(fmsFileSystemService.getFileLocalPath(fsUploadRecord.getUniqueId() , fsUploadRecord.getOrigFileName())), outputStream);
+ } catch (AppException e) {
+ String errorCode = e.getErrorCode();
+ response.setStatus(Integer.parseInt(errorCode));
+ return;
+ } catch (IOException e) {
+ response.setStatus(500);
+ return;
+ }
+ }
+
+ @GetMapping("File/getFileBase64")
+ @Logable
+ public CommonResult getFileBase64(@RequestParam("uniqueId")String uniqueId){
+ FmsDetailRecordResult fsUploadRecord = fmsFileSystemService.getFileUploadRecord(uniqueId);
+ try {
+ String path = fmsFileSystemService.getFileLocalPath(fsUploadRecord.getUniqueId() , fsUploadRecord.getOrigFileName());
+ File file = new File(path);
+ FileInputStream fileInputStream = new FileInputStream(file);
+ byte[] buffer = new byte[(int)file.length()];
+ fileInputStream.read(buffer);
+ fileInputStream.close();
+ return CommonResult.success(new BASE64Encoder().encode(buffer));
+ } catch (Exception e) {
+ LOGGER.error(FmsCodeBean.FmsCode.ERROR_TRANS_BASE64.code, e);
+ throw new AppException(FmsCodeBean.FmsCode.ERROR_TRANS_BASE64.code, FmsCodeBean.FmsCode.ERROR_TRANS_BASE64.message);
+ }
+ }
+
+ /**
+ * 此接口不对外开放,仅供内部微服务使用
+ * @param base64Req
+ * @return
+ */
+ @PostMapping("File/BaseSixFour")
+ @Logable
+ @ApiOperation(value = "文件上传", notes = "文件上传", httpMethod = "POST")
+ public CommonResult uploadFileBase64(@RequestBody(required = true) FmsBase64FileUploadRequest base64Req) {
+ FmsUploadTokenResult fsUploadToken = fmsBusinessTypeService.getFsBusinessTypeByUploadToken(base64Req.getUploadToken());
+ if (fsUploadToken == null) {
+ throw new AppException(FmsCodeBean.FmsCode.ERROR_TIMEOUT.code);
+ }
+ FmsBusinessTypeResult fsBusinessType = fsUploadToken.getFsBusinessType();
+ byte[] fileBytes;
+ try {
+ //将字符串转换为byte数组
+ fileBytes = Base64Utils.decode(base64Req.getFileBaseSixFour());
+ } catch (Exception e) {
+ throw new AppException(FmsCodeBean.FmsCode.FAIL.code);
+ }
+
+ String fsSize = fsBusinessType.getFsSize();
+ Long limitSize = Long.parseLong(fsSize);
+ long fileSize = fileBytes.length;
+ int mult = 1024;
+ if (fileSize > (limitSize * mult)) {
+ throw new AppException(FmsCodeBean.FmsCode.ERROR_FILESIZE_OUT_OFF_LIMIT.code);
+ }
+ if (!fsBusinessType.getBusinessType().equals(base64Req.getBusinessType())) {
+ // 文件类型不一致
+ throw new AppException(FmsCodeBean.FmsCode.ERROR_FILETYPE.code);
+ }
+ FmsBusinessTypeParam fmsBusinessTypeParam = new FmsBusinessTypeParam();
+ BeanUtils.copyProperties(fsBusinessType , fmsBusinessTypeParam);
+ FmsUploadTokenParam fmsUploadTokenParam = new FmsUploadTokenParam();
+ BeanUtils.copyProperties(fsUploadToken , fmsUploadTokenParam);
+ String fileUploadResponse = fmsFileSystemService.saveFileFromBytes(fileBytes, base64Req.getFileName(), fmsBusinessTypeParam, fmsUploadTokenParam);
+ fmsBusinessTypeService.deleteFsBusinessTypeByUploadToken(base64Req.getUploadToken());
+ return CommonResult.success(fileUploadResponse);
+ }
+
+ /**
+ * 返回文件的唯一ID
+ * @param file
+ * @param uploadToken
+ * @return
+ */
+ @PostMapping("File")
+ @Logable
+ @ApiOperation(value = "文件上传", notes = "文件上传", httpMethod = "POST")
+ @ApiImplicitParams({
+ @ApiImplicitParam(name = "uploadToken", value = "文件上传token", required = true, dataType = "String", paramType = "query")
+ })
+ public CommonResult fileUpload(@RequestPart(name = "file", required = true) MultipartFile file,
+ String uploadToken,
+ String fileName) {
+ //压缩过后的文件名称前端无法获取,额外的字段标识
+ String originalFilename = file.getOriginalFilename();
+ if (!StringUtils.isBlank(fileName)){
+ originalFilename = fileName;
+ }
+ FmsFileUploadResult response = new FmsFileUploadResult();
+ if (file == null || StringUtils.isBlank(originalFilename)) {
+ // 文件不能为空
+ throw new AppException(FmsCodeBean.FmsCode.ERROR_FILE_IS_NULL.code);
+ }
+ FmsUploadTokenResult fsUploadToken = fmsBusinessTypeService.getFsBusinessTypeByUploadToken(uploadToken);
+ if (fsUploadToken == null) {
+ throw new AppException(FmsCodeBean.FmsCode.ERROR_TIMEOUT.code);
+ }
+ FmsBusinessTypeResult fsBusinessType = fsUploadToken.getFsBusinessType();
+ String fsSize = fsBusinessType.getFsSize();
+ Long limitSize = Long.parseLong(fsSize);
+ long fileSize = file.getSize();
+ int mult = 102400;
+ if (fileSize > (limitSize * mult)) {
+ throw new AppException(FmsCodeBean.FmsCode.ERROR_FILESIZE_OUT_OFF_LIMIT.code);
+ }
+ String fsType = fsBusinessType.getFsType();
+ if (StringUtils.equals(fsType, "currency")){
+ //如果取值为currency,则不判断类型
+ }else {
+ String suffix = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
+ String contentType = file.getContentType();
+ if (contentType == null || !fsType.contains(suffix.trim().toLowerCase()) || !fsType.contains(contentType)) {
+ LOGGER.error(FmsCodeBean.FmsCode.ERROR_FILETYPE.code, "文件类型:" + suffix + " || " + contentType);
+ // 文件后缀错误
+ throw new AppException(FmsCodeBean.FmsCode.ERROR_FILETYPE.code);
+ }
+ }
+
+ FmsUploadTokenParam param = new FmsUploadTokenParam();
+ BeanUtils.copyProperties(fsUploadToken , param);
+ param.setOriginalFilename(originalFilename);
+ String uniqueId = fmsFileSystemService.saveFile(file, param);
+ fmsBusinessTypeService.deleteFsBusinessTypeByUploadToken(uploadToken);
+ response.setUniqueId(uniqueId);
+ return CommonResult.success(response);
+ }
+
+ /**
+ * 文件批量上传
+ * @param files 文件
+ * @param uploadToken 申请的token
+ * @return
+ */
+ @PostMapping("/Files")
+ @Logable
+ @ApiOperation(value = "批量上传文件", notes = "批量上传文件", httpMethod = "POST")
+ @ApiImplicitParams({
+ @ApiImplicitParam(name = "uploadToken", value = "文件上传token", required = true, dataType = "String", paramType = "query")
+ })
+ public CommonResult filesMultipartUpload(@RequestPart(name = "files", required = true) MultipartFile[] files, String uploadToken) {
+
+ return fmsFileSystemService.filesMultipartUpload(files,uploadToken);
+ }
+
+ @ApiOperation(value = "下载zip压缩文件接口", notes = "下载zip压缩文件接口", httpMethod = "GET")
+ @Logable
+ @RequestMapping(value = "/download/zip",method = RequestMethod.GET)
+ public void downloadZipByUniqueIds(@RequestParam("uniqueIds") List uniqueIds,
+ @RequestParam(value = "zipName", required = false) String zipName,
+ HttpServletResponse response) throws IOException {
+ if (StringUtils.isBlank(zipName)) {
+ zipName = "attachment";
+ }
+ List paths = new ArrayList<>();
+ List files = new ArrayList<>();
+ for (String uniqueId : uniqueIds) {
+ FmsDetailRecordResult fsUploadRecord = fmsFileSystemService.getFileUploadRecord(uniqueId);
+ String path = fmsFileSystemService.getFileLocalPath(uniqueId, fsUploadRecord.getOrigFileName());
+ paths.add(path);
+ File file = new File(path);
+ files.add(file);
+ }
+ try {
+ response.setContentType("application/zip");
+ response.setHeader("Content-Disposition", "attachment; fileName=" + URLEncoder.encode(zipName + ".zip", "utf-8"));
+ OutputStream outputStream = response.getOutputStream();
+ ZipUtils.toZip(files, outputStream);
+ } catch (FileNotFoundException e) {
+ throw new AppException(FmsCodeBean.FmsCode.NOT_EXIST_FILE.code);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/itools-fms/itools-fms-server/src/main/java/com/itools/core/controller/TestController.java b/itools-fms/itools-fms-server/src/main/java/com/itools/core/controller/TestController.java
new file mode 100644
index 0000000000000000000000000000000000000000..2ad997e7358deda46f1eab8aaa8e2e627683cd4e
--- /dev/null
+++ b/itools-fms/itools-fms-server/src/main/java/com/itools/core/controller/TestController.java
@@ -0,0 +1,35 @@
+package com.itools.core.controller;
+
+import com.itools.core.base.CommonResult;
+import com.itools.core.context.FileStrategyServiceContext;
+import com.itools.core.em.StrategyType;
+import com.itools.core.service.FileManagerService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @project: itools-backend
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-04-01 16:23
+ */
+@RestController
+public class TestController {
+ @Qualifier("fastDfsFileManagerServiceImpl")
+ @Autowired
+ private FileManagerService fileManagerService;
+
+ @Autowired
+ private FileStrategyServiceContext fileStrategyServiceContext;
+ @GetMapping("/test")
+ public CommonResult test(){
+ FileManagerService fileManagerService2 = fileStrategyServiceContext.get(StrategyType.NIO.getType());
+ return fileManagerService2.mutipartUploadFiles();
+ }
+ @GetMapping("/test2")
+ public CommonResult test2(){
+ return fileManagerService.mutipartUploadFiles();
+ }
+}
diff --git a/itools-fms/itools-fms-server/src/main/java/com/itools/core/mapper/FmsAccessTokenMapper.java b/itools-fms/itools-fms-server/src/main/java/com/itools/core/mapper/FmsAccessTokenMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..e770dbd97ae9aeebf5f4537c6735abe1886b1114
--- /dev/null
+++ b/itools-fms/itools-fms-server/src/main/java/com/itools/core/mapper/FmsAccessTokenMapper.java
@@ -0,0 +1,34 @@
+package com.itools.core.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.itools.core.dto.accessToken.FmsAccessTokenDTO;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+
+/**
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-03-28 15:51
+ */
+@Repository
+public interface FmsAccessTokenMapper extends BaseMapper {
+
+
+ /**
+ * 根据主键(fileAccessToken)查询
+ *
+ * @param fileAccessToken
+ * @return
+ */
+ FmsAccessTokenDTO selectByPrimaryKey(String fileAccessToken);
+
+ /**
+ * 批量插入
+ * @param records
+ * @return
+ */
+ int multipartInsert(@Param("records") List records);
+}
\ No newline at end of file
diff --git a/itools-fms/itools-fms-server/src/main/java/com/itools/core/mapper/FmsBusinessTypeMapper.java b/itools-fms/itools-fms-server/src/main/java/com/itools/core/mapper/FmsBusinessTypeMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..7fd866bf82157577ba2a9746da4123871cbdf413
--- /dev/null
+++ b/itools-fms/itools-fms-server/src/main/java/com/itools/core/mapper/FmsBusinessTypeMapper.java
@@ -0,0 +1,52 @@
+package com.itools.core.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.itools.core.dto.businessType.FmsBusinessTypeDTO;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+/**
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-03-28 15:51
+ */
+@Repository
+public interface FmsBusinessTypeMapper extends BaseMapper {
+ /**
+ * 根据主键删除
+ * @param id
+ * @return
+ */
+ int deleteByPrimaryKey(Long id);
+
+ /**
+ * 插入非空参数
+ * @param record
+ * @return
+ */
+ int insertSelective(FmsBusinessTypeDTO record);
+ /**
+ * 根据主键查询
+ * @param id
+ * @return
+ */
+ FmsBusinessTypeDTO selectByPrimaryKey(Long id);
+ /**
+ * 根据主键更新非空参数
+ * @param record
+ * @return
+ */
+ int updateByPrimaryKeySelective(FmsBusinessTypeDTO record);
+ /**
+ * 根据主键更新所有参数
+ * @param record
+ * @return
+ */
+ int updateByPrimaryKey(FmsBusinessTypeDTO record);
+ /**
+ * 根据入参条件查询
+ * @param record
+ * @return
+ */
+ List selectBySelective(FmsBusinessTypeDTO record);
+}
\ No newline at end of file
diff --git a/itools-fms/itools-fms-server/src/main/java/com/itools/core/mapper/FmsFileRecordMapper.java b/itools-fms/itools-fms-server/src/main/java/com/itools/core/mapper/FmsFileRecordMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..28a6eb7539fafa1b4ca8c897ef3c591bd218dd7a
--- /dev/null
+++ b/itools-fms/itools-fms-server/src/main/java/com/itools/core/mapper/FmsFileRecordMapper.java
@@ -0,0 +1,54 @@
+package com.itools.core.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.itools.core.dto.fileRecord.FmsRecordDTO;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+/**
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-03-28 15:51
+ */
+@Repository
+public interface FmsFileRecordMapper extends BaseMapper {
+
+ /**
+ * 根据主键更新非空参数
+ * @param record
+ * @return
+ */
+ int updateByPrimaryKeySelective(FmsRecordDTO record);
+
+ /**
+ * 根据入参条件查询
+ * @param record
+ * @return
+ */
+ List selectbySelective(FmsRecordDTO record);
+ /**
+ * 插入非空参数
+ * @param record
+ * @return
+ */
+ int insertSelective(FmsRecordDTO record);
+ /**
+ * 根据主键查询
+ * @param id
+ * @return
+ */
+ FmsRecordDTO selectByPrimaryKey(Long id);
+ /**
+ * 根据主键删除
+ * @param id
+ * @return
+ */
+ int deleteByPrimaryKey(Long id);
+ /**
+ * 根据主键更新所有参数
+ * @param record
+ * @return
+ */
+ int updateByPrimaryKey(FmsRecordDTO record);
+
+}
\ No newline at end of file
diff --git a/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/FmsAccessTokenService.java b/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/FmsAccessTokenService.java
new file mode 100644
index 0000000000000000000000000000000000000000..0cd8e5fbd93873f140bc679593f99e32c7d47d9d
--- /dev/null
+++ b/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/FmsAccessTokenService.java
@@ -0,0 +1,40 @@
+package com.itools.core.service;
+
+
+import com.itools.core.result.FmsAccessTokenResult;
+
+/**
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-04-01 11:26
+ */
+public interface FmsAccessTokenService {
+
+ /**
+ * 从缓存中获取FsAccessToken信息
+ *
+ * @param fileAccessToken
+ * @return
+ */
+ FmsAccessTokenResult getFileAccessToken(String fileAccessToken);
+
+ /**
+ * 缓存FsAccessToken信息
+ *
+ * @param fileAccessToken
+ * @param expiredTime
+ * @param maxAccessCount
+ * @param uniqueId
+ * @param type
+ * @return
+ */
+ FmsAccessTokenResult cacheFileAccessToken(String fileAccessToken, int expiredTime, int maxAccessCount, String uniqueId, String type);
+
+
+ /**
+ * 删除缓存数据
+ *
+ * @param fileAccessToken
+ */
+ void deleteFileAccessToken(String fileAccessToken);
+}
diff --git a/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/FmsBusinessTypeService.java b/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/FmsBusinessTypeService.java
new file mode 100644
index 0000000000000000000000000000000000000000..488b149faaa71470f62cde0d109f030bab5a224d
--- /dev/null
+++ b/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/FmsBusinessTypeService.java
@@ -0,0 +1,42 @@
+package com.itools.core.service;
+
+
+import com.itools.core.param.FmsUploadTokenParam;
+import com.itools.core.result.FmsUploadTokenResult;
+import com.itools.core.result.FmsBusinessTypeResult;
+
+import java.util.List;
+
+/**
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-04-01 11:26
+ */
+public interface FmsBusinessTypeService {
+
+ /**
+ * 查询FsBusinessType列表
+ *
+ * @param businessType
+ * @return
+ */
+ List queryFsBusinessTypeList(String businessType);
+
+ /**
+ * 根据 uploadToken ,缓存FsBusinessType对象
+ *
+ * @param uploadToken
+ * @return
+ */
+ FmsUploadTokenResult cacheFsUploadToken(String uploadToken, FmsUploadTokenParam fsUploadToken);
+
+ /**
+ * 根据 uploadToken ,获取FsBusinessType对象
+ *
+ * @param uploadToken
+ * @return
+ */
+ FmsUploadTokenResult getFsBusinessTypeByUploadToken(String uploadToken);
+
+ void deleteFsBusinessTypeByUploadToken(String uploadToken);
+}
diff --git a/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/FmsFileSystemService.java b/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/FmsFileSystemService.java
new file mode 100644
index 0000000000000000000000000000000000000000..3f8cae691f31043a952840fc61d3b6df94f4da6d
--- /dev/null
+++ b/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/FmsFileSystemService.java
@@ -0,0 +1,128 @@
+package com.itools.core.service;
+
+import com.itools.core.base.CommonResult;
+import com.itools.core.param.FmsAccessTokenParam;
+import com.itools.core.param.FmsUploadTokenParam;
+import com.itools.core.param.FmsBusinessTypeParam;
+import com.itools.core.result.FmsBusinessTypeResult;
+import com.itools.core.result.FmsDetailRecordResult;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.List;
+
+/**
+ * @project: itools-backend
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-04-01 11:26
+ */
+public interface FmsFileSystemService {
+
+ /**
+ * 根据uniqeId和文件名得到本地文件存储路径
+ * @param uniqueId
+ * @param fileName
+ * @return
+ */
+ String getFileLocalPath(String uniqueId, String fileName);
+
+
+
+ /**
+ * 存储文件
+ *
+ * @param file
+ * @param fsUploadToken
+ * @return
+ */
+ String saveFile(MultipartFile file, FmsUploadTokenParam fsUploadToken);
+
+
+
+ /**
+ * 申请文件上传token
+ * @param businessType
+ * @param fromSystemId
+ * @param needEncrypt
+ * @param remark
+ * @return
+ */
+ String applyUploadToken(String businessType, String fromSystemId, String needEncrypt, String remark);
+
+
+ /**
+ * 存储文件
+ * 使用字节流输入文件
+ * 返回文件的全局唯一ID
+ * @param fileBytes
+ * @param fileName
+ * @param fsBusinessType
+ * @param fsUploadToken
+ * @return
+ */
+ String saveFileFromBytes(byte[] fileBytes, String fileName, FmsBusinessTypeParam fsBusinessType, FmsUploadTokenParam fsUploadToken);
+
+
+
+
+ /**
+ * 获取文件访问路径,如果超时时间设置为小于等于0,那么返回的有效路径可以永久访问
+ *
+ * @param uniqueId
+ * @param expiredTime
+ * @param maxAccessCount
+ * @return
+ */
+ String getFileUrlByFileId(String uniqueId, int expiredTime, int maxAccessCount, String type);
+
+ /**
+ * 获得uniqueId对应的文件上传记录
+ * 会检查
+ * @param fsAccessToken
+ * @param uniqueId
+ * @param fileAccessToken
+ * @return
+ */
+ FmsDetailRecordResult getFileUploadRecord(FmsAccessTokenParam fsAccessToken, String uniqueId, String fileAccessToken);
+
+
+ /**
+ * 获得uniqueId对应的文件上传记录
+ * @param uniqueId
+ * @return
+ */
+ FmsDetailRecordResult getFileUploadRecord(String uniqueId);
+
+ /**
+ * 文件批量上传
+ * @param files
+ * @param param
+ * @return
+ */
+ CommonResult uploadFiles(MultipartFile[] files, FmsUploadTokenParam param);
+
+ /**
+ * 验证文件
+ * @param files
+ * @param fsBusinessType
+ */
+ void verifyFiles(MultipartFile[] files, FmsBusinessTypeResult fsBusinessType);
+
+ /**
+ * 文件批量上传的业务逻辑
+ * @param files
+ * @param uploadToken
+ * @return
+ */
+ CommonResult filesMultipartUpload(MultipartFile[] files, String uploadToken);
+
+ /**
+ * 获取文件访问路径,如果超时时间设置为小于等于0,那么返回的有效路径可以永久访问
+ * @param uniqueIds
+ * @param expiredTime
+ * @param maxAccessCount
+ * @param type
+ * @return
+ */
+ CommonResult getFileUrlByFileIds(List uniqueIds, Integer expiredTime, int maxAccessCount, String type);
+}
diff --git a/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/FmsRecordService.java b/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/FmsRecordService.java
new file mode 100644
index 0000000000000000000000000000000000000000..0df6b921120361a7b198c3a63f045168b9e4ab9c
--- /dev/null
+++ b/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/FmsRecordService.java
@@ -0,0 +1,16 @@
+package com.itools.core.service;
+
+
+import com.itools.core.result.FmsDetailRecordResult;
+
+/**
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-04-01 11:26
+ */
+public interface FmsRecordService {
+
+
+ FmsDetailRecordResult queryFssRecordByUniqueId(String uniqueId);
+
+}
diff --git a/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/impl/FmsAccessTokenServiceImpl.java b/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/impl/FmsAccessTokenServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..be0b5dedfe30145eafaea2499d455b2c627c68eb
--- /dev/null
+++ b/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/impl/FmsAccessTokenServiceImpl.java
@@ -0,0 +1,126 @@
+package com.itools.core.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.itools.core.dto.accessToken.FmsAccessTokenDTO;
+import com.itools.core.em.FmsCodeBean;
+import com.itools.core.exception.AppException;
+import com.itools.core.log.Logable;
+import com.itools.core.mapper.FmsAccessTokenMapper;
+import com.itools.core.result.FmsAccessTokenResult;
+import com.itools.core.service.FmsAccessTokenService;
+import com.itools.core.utils.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-03-28 15:51
+ */
+@Service
+public class FmsAccessTokenServiceImpl implements FmsAccessTokenService {
+
+ @Autowired
+ private RedisTemplate redisTemplate;
+ @Autowired
+ private FmsAccessTokenMapper fmsAccessTokenMapper;
+ /**
+ * 从缓存中或者数据库中获取FsAccessToken信息
+ *
+ * @param fileAccessToken
+ * @return
+ */
+ @Override
+ public FmsAccessTokenResult getFileAccessToken(String fileAccessToken) {
+ Object object = redisTemplate.opsForValue().get(fileAccessToken);
+ if (object != null){
+ FmsAccessTokenResult result = JSON.parseObject((String) object, FmsAccessTokenResult.class);
+ return result;
+ }else {
+ FmsAccessTokenDTO fssFmsAccessTokenDto = fmsAccessTokenMapper.selectByPrimaryKey(fileAccessToken);
+ if (fssFmsAccessTokenDto == null){
+ return null;
+ }
+ FmsAccessTokenResult result = new FmsAccessTokenResult();
+ BeanUtils.copyProperties(fssFmsAccessTokenDto, result);
+ return result;
+ }
+ }
+
+ /**
+ * 缓存FsAccessToken信息,如果过期时间小于等于0,则会将accessToken持久化(缓存到数据库)
+ * @param fileAccessToken
+ * @param expiredTime
+ * @param maxAccessCount
+ * @param uniqueId
+ * @param type
+ * @return
+ */
+ @Override
+ public FmsAccessTokenResult cacheFileAccessToken(String fileAccessToken, int expiredTime, int maxAccessCount, String uniqueId, String type) {
+ if (StringUtils.isBlank(fileAccessToken)) {
+ throw new AppException(FmsCodeBean.FmsCode.FAIL.code);
+ }
+ FmsAccessTokenResult fmsAccessTokenResult = new FmsAccessTokenResult(expiredTime, maxAccessCount, uniqueId, type);
+ if (expiredTime > 0){
+ redisTemplate.opsForValue().set(fileAccessToken , JSON.toJSONString(fmsAccessTokenResult) , expiredTime , TimeUnit.MINUTES);
+ }else {
+ FmsAccessTokenDTO fssFmsAccessTokenDto = new FmsAccessTokenDTO();
+ fssFmsAccessTokenDto.setFileAccessToken(fileAccessToken);
+ fssFmsAccessTokenDto.setType(type);
+ fssFmsAccessTokenDto.setUniqueId(uniqueId);
+ fmsAccessTokenMapper.insert(fssFmsAccessTokenDto);
+ }
+ return fmsAccessTokenResult;
+ }
+ /**
+ * 缓存FsAccessToken信息,如果过期时间小于等于0,则会将accessToken持久化(缓存到数据库)
+ * @param fileAccessToken
+ * @param expiredTime
+ * @param maxAccessCount
+ * @param uniqueIds
+ * @param type
+ * @return
+ */
+ public List cacheFileAccessToken(String fileAccessToken, int expiredTime, int maxAccessCount, List uniqueIds, String type) {
+ if (StringUtils.isBlank(fileAccessToken)) {
+ throw new AppException(FmsCodeBean.FmsCode.FAIL.code);
+ }
+ List fssAccessTokens = new ArrayList<>();
+ for (String uniqueId : uniqueIds){
+ FmsAccessTokenResult fmsAccessTokenResult = new FmsAccessTokenResult(expiredTime, maxAccessCount, uniqueId, type);
+ if (expiredTime > 0){
+ redisTemplate.opsForValue().set(fileAccessToken , JSON.toJSONString(fmsAccessTokenResult) , expiredTime , TimeUnit.MINUTES);
+ }else {
+ FmsAccessTokenDTO fssFmsAccessTokenDto = new FmsAccessTokenDTO();
+ fssFmsAccessTokenDto.setFileAccessToken(fileAccessToken);
+ fssFmsAccessTokenDto.setType(type);
+ fssFmsAccessTokenDto.setUniqueId(uniqueId);
+ fssAccessTokens.add(fssFmsAccessTokenDto);
+ }
+ }
+ if (!CollectionUtils.isEmpty(fssAccessTokens)){
+ fmsAccessTokenMapper.multipartInsert(fssAccessTokens);
+ }
+ return fssAccessTokens;
+ }
+
+ /**
+ * 删除缓存数据
+ *
+ * @param fileAccessToken
+ */
+ @Override
+ @CacheEvict(value = "fileAccessToken", key = "#fileAccessToken")
+ @Logable(businessTag = "FsAccessService")
+ public void deleteFileAccessToken(String fileAccessToken) {
+ }
+}
diff --git a/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/impl/FmsBusinessTypeServiceImpl.java b/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/impl/FmsBusinessTypeServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..b61c808b63027ca0ce928d3a3441fcaaee0375f5
--- /dev/null
+++ b/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/impl/FmsBusinessTypeServiceImpl.java
@@ -0,0 +1,88 @@
+package com.itools.core.service.impl;
+
+import com.itools.core.dto.businessType.FmsBusinessTypeDTO;
+import com.itools.core.log.Logable;
+import com.itools.core.mapper.FmsBusinessTypeMapper;
+import com.itools.core.param.FmsUploadTokenParam;
+import com.itools.core.result.FmsUploadTokenResult;
+import com.itools.core.result.FmsBusinessTypeResult;
+import com.itools.core.service.FmsBusinessTypeService;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-03-28 15:51
+ */
+@Service
+public class FmsBusinessTypeServiceImpl implements FmsBusinessTypeService {
+ @Autowired
+ private FmsBusinessTypeMapper fmsBusinessTypeMapper;
+
+ /**
+ * 查询FsBusinessType列表
+ *
+ * @param businessType
+ * @return
+ */
+ @Override
+ @Cacheable(value = "fsBusinessTypes", key = "#businessType")
+ @Logable
+ public List queryFsBusinessTypeList(String businessType) {
+ if (StringUtils.isBlank(businessType)) {
+ return null;
+ }
+ FmsBusinessTypeDTO tmp = new FmsBusinessTypeDTO();
+ tmp.setBusinessType(businessType);
+ List fssBusinessTypes = fmsBusinessTypeMapper.selectBySelective(tmp);
+ List fmsBusinessTypeResults = new ArrayList<>();
+ for (FmsBusinessTypeDTO fssBusinessType : fssBusinessTypes){
+ FmsBusinessTypeResult fmsBusinessTypeResult = new FmsBusinessTypeResult();
+ BeanUtils.copyProperties(fssBusinessType , fmsBusinessTypeResult);
+ fmsBusinessTypeResults.add(fmsBusinessTypeResult);
+ }
+ return fmsBusinessTypeResults;
+ }
+
+ /**
+ * 根据 uploadToken ,缓存FsBusinessType对象
+ *
+ * @param uploadToken
+ * @return
+ */
+ @Override
+ @Cacheable(value = "fsBusinessType", key = "#uploadToken")
+ @Logable
+ public FmsUploadTokenResult cacheFsUploadToken(String uploadToken, FmsUploadTokenParam fmsUploadTokenParam) {
+ FmsUploadTokenResult result = new FmsUploadTokenResult();
+ BeanUtils.copyProperties(fmsUploadTokenParam, result);
+ return result;
+ }
+
+ /**
+ * 根据 uploadToken ,获取FsBusinessType对象
+ *
+ * @param uploadToken
+ * @return
+ */
+ @Override
+ @Cacheable(value = "fsBusinessType", key = "#uploadToken")
+ @Logable
+ public FmsUploadTokenResult getFsBusinessTypeByUploadToken(String uploadToken) {
+ return null;
+ }
+
+ @Override
+ @CacheEvict(value = "fsBusinessType", key = "#uploadToken")
+ @Logable
+ public void deleteFsBusinessTypeByUploadToken(String uploadToken) {
+ }
+}
diff --git a/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/impl/FmsFileSystemServiceImpl.java b/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/impl/FmsFileSystemServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..cb04324c02c1ce149f4cd0c846663be7dae4c96b
--- /dev/null
+++ b/itools-fms/itools-fms-server/src/main/java/com/itools/core/service/impl/FmsFileSystemServiceImpl.java
@@ -0,0 +1,565 @@
+package com.itools.core.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.itools.core.base.CommonResult;
+import com.itools.core.dto.accessToken.FmsAccessTokenDTO;
+import com.itools.core.dto.fileRecord.FmsRecordDTO;
+import com.itools.core.em.FmsCodeBean;
+import com.itools.core.em.FmsConstants;
+import com.itools.core.exception.AppException;
+import com.itools.core.log.Logable;
+import com.itools.core.mapper.FmsAccessTokenMapper;
+import com.itools.core.mapper.FmsFileRecordMapper;
+import com.itools.core.param.FmsAccessTokenParam;
+import com.itools.core.param.FmsUploadTokenParam;
+import com.itools.core.param.FmsBusinessTypeParam;
+import com.itools.core.result.*;
+import com.itools.core.service.FmsFileSystemService;
+import com.itools.core.service.impl.task.MyUploadFileTask;
+import com.itools.core.snowflake.SequenceService;
+import com.itools.core.utils.CollectionUtils;
+import com.itools.core.utils.UUIDUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.FileCopyUtils;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @description:
+ * @author: XUCHANG
+ * @create: 2021-03-28 15:51
+ */
+@Service
+public class FmsFileSystemServiceImpl implements FmsFileSystemService {
+
+
+ @Value("${fileStoreRootPath}")
+ String fileStoreRootPath;
+
+ @Value("${fileAccessUrlForOutter}")
+ String fileAccessUrlForOutter;
+
+ @Value("${fileUploadLimitSize}")
+ Integer fileUploadLimitSize;
+
+ @Value("${fileMaxRequestSize}")
+ Integer fileMaxRequestSize;
+
+ @Value("${fileMaxFileSize}")
+ Integer fileMaxFileSize;
+
+ @Autowired
+ FmsFileSystemServiceImpl self;
+
+ @Autowired
+ SequenceService sequenceService;
+
+ @Autowired
+ FmsBusinessTypeServiceImpl fmsBusinessTypeService;
+
+ @Autowired
+ RedisTemplate