Ver Fonte

腾讯云对象存储

yingp há 6 anos atrás
pai
commit
5a5088f745
40 ficheiros alterados com 998 adições e 120 exclusões
  1. 41 0
      base-servers/file/file-server-fdfs/pom.xml
  2. 1 1
      base-servers/file/file-server-fdfs/src/main/docker/Dockerfile
  3. 5 8
      base-servers/file/file-server-fdfs/src/main/java/com/usoftchina/smartschool/file/fdfs/FdfsFileApplication.java
  4. 11 11
      base-servers/file/file-server-fdfs/src/main/resources/application.yml
  5. 1 4
      base-servers/file/file-server-fdfs/src/main/resources/config/application-docker-prod.yml
  6. 0 0
      base-servers/file/file-server-fdfs/src/main/resources/config/application-docker.yml
  7. 0 0
      base-servers/file/file-server-fdfs/src/main/resources/logback-spring.xml
  8. 41 0
      base-servers/file/file-server-qcloud/pom.xml
  9. 6 0
      base-servers/file/file-server-qcloud/src/main/docker/Dockerfile
  10. 26 0
      base-servers/file/file-server-qcloud/src/main/java/com/usoftchina/smartschool/file/qcloud/QCloudFileApplication.java
  11. 97 0
      base-servers/file/file-server-qcloud/src/main/resources/application.yml
  12. 7 0
      base-servers/file/file-server-qcloud/src/main/resources/config/application-docker-prod.yml
  13. 131 0
      base-servers/file/file-server-qcloud/src/main/resources/logback-spring.xml
  14. 2 19
      base-servers/file/file-server/pom.xml
  15. 5 12
      base-servers/file/file-server/src/main/java/com/usoftchina/smartschool/file/controller/FileController.java
  16. 15 21
      base-servers/file/file-server/src/main/java/com/usoftchina/smartschool/file/po/FileInfo.java
  17. 0 13
      base-servers/file/file-server/src/main/resources/config/application-dev.yml
  18. 0 12
      base-servers/file/file-server/src/main/resources/config/application-docker-dev.yml
  19. 0 12
      base-servers/file/file-server/src/main/resources/config/application-docker-test.yml
  20. 0 0
      base-servers/file/file-server/src/main/resources/i18n/messages_en_US.properties
  21. 0 0
      base-servers/file/file-server/src/main/resources/i18n/messages_zh_CN.properties
  22. 24 0
      base-servers/file/file-storage-fdfs/pom.xml
  23. 21 0
      base-servers/file/file-storage-fdfs/src/main/java/com/usoftchina/smartschool/file/storage/fdfs/FdfsConfig.java
  24. 50 0
      base-servers/file/file-storage-fdfs/src/main/java/com/usoftchina/smartschool/file/storage/fdfs/FdfsFileStorageClient.java
  25. 3 0
      base-servers/file/file-storage-fdfs/src/main/resources/META-INF/spring.factories
  26. 35 0
      base-servers/file/file-storage-qcloud/pom.xml
  27. 81 0
      base-servers/file/file-storage-qcloud/src/main/java/com/usoftchina/smartschool/file/storage/qcloud/COSFileStorageClient.java
  28. 58 0
      base-servers/file/file-storage-qcloud/src/main/java/com/usoftchina/smartschool/file/storage/qcloud/CosProperties.java
  29. 24 0
      base-servers/file/file-storage-qcloud/src/main/java/com/usoftchina/smartschool/file/storage/qcloud/QCloudConfig.java
  30. 3 0
      base-servers/file/file-storage-qcloud/src/main/resources/META-INF/spring.factories
  31. 37 0
      base-servers/file/file-storage-qcloud/src/test/java/com/usoftchina/smartschool/file/storage/qcloud/COSFileStorageClientTest.java
  32. 49 0
      base-servers/file/file-storage-qcloud/src/test/java/com/usoftchina/smartschool/file/storage/qcloud/RandomTextFile.java
  33. 15 0
      base-servers/file/file-storage/pom.xml
  34. 44 0
      base-servers/file/file-storage/src/main/java/com/usoftchina/smartschool/file/storage/FileMetadata.java
  35. 39 0
      base-servers/file/file-storage/src/main/java/com/usoftchina/smartschool/file/storage/FileStorageClient.java
  36. 1 1
      base-servers/file/file-storage/src/main/java/com/usoftchina/smartschool/file/storage/util/FileType.java
  37. 3 6
      base-servers/file/file-storage/src/main/java/com/usoftchina/smartschool/file/storage/util/FileTypeUtils.java
  38. 97 0
      base-servers/file/file-storage/src/main/java/com/usoftchina/smartschool/file/storage/util/FilenameUtils.java
  39. 5 0
      base-servers/file/pom.xml
  40. 20 0
      pom.xml

+ 41 - 0
base-servers/file/file-server-fdfs/pom.xml

@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>file</artifactId>
+        <groupId>com.usoftchina.smartschool</groupId>
+        <version>1.0.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>file-server-fdfs</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.usoftchina.smartschool</groupId>
+            <artifactId>file-server</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.usoftchina.smartschool</groupId>
+            <artifactId>file-storage-fdfs</artifactId>
+        </dependency>
+        <!-- test -->
+        <dependency>
+            <groupId>com.usoftchina.smartschool</groupId>
+            <artifactId>test-starter</artifactId>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>com.spotify</groupId>
+                <artifactId>docker-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 1 - 1
base-servers/file/file-server/src/main/docker/Dockerfile → base-servers/file/file-server-fdfs/src/main/docker/Dockerfile

@@ -1,6 +1,6 @@
 FROM frolvlad/alpine-oraclejdk8:slim
 VOLUME /tmp
-ADD file-server-1.0.0-SNAPSHOT.jar app.jar
+ADD file-server-fdfs-1.0.0-SNAPSHOT.jar app.jar
 RUN sh -c 'touch /app.jar'
 ENV JAVA_OPTS=""
 ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]

+ 5 - 8
base-servers/file/file-server/src/main/java/com/usoftchina/smartschool/file/FileApplication.java → base-servers/file/file-server-fdfs/src/main/java/com/usoftchina/smartschool/file/fdfs/FdfsFileApplication.java

@@ -1,29 +1,26 @@
-package com.usoftchina.smartschool.file;
+package com.usoftchina.smartschool.file.fdfs;
 
-import com.github.tobato.fastdfs.FdfsClientConfig;
 import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
 import org.springframework.context.annotation.EnableMBeanExport;
-import org.springframework.context.annotation.Import;
 import org.springframework.jmx.support.RegistrationPolicy;
 import org.springframework.transaction.annotation.EnableTransactionManagement;
 import springfox.documentation.swagger2.annotations.EnableSwagger2;
 
 /**
  * @author yingp
- * @date 2018/9/29
+ * @date 2019/3/14
  */
-@SpringBootApplication
+@SpringBootApplication(scanBasePackages = "com.usoftchina.smartschool.file")
 @EnableEurekaClient
 @EnableTransactionManagement
 @MapperScan("com.usoftchina.smartschool.file.mapper")
-@Import(FdfsClientConfig.class)
 @EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
 @EnableSwagger2
-public class FileApplication {
+public class FdfsFileApplication {
     public static void main(String[] args) {
-        SpringApplication.run(FileApplication.class, args);
+        SpringApplication.run(FdfsFileApplication.class, args);
     }
 }

+ 11 - 11
base-servers/file/file-server/src/main/resources/application.yml → base-servers/file/file-server-fdfs/src/main/resources/application.yml

@@ -1,3 +1,13 @@
+fdfs:
+  so-timeout: 1500
+  connect-timeout: 600
+  thumb-image:
+    width: 150
+    height: 150
+  tracker-list:
+    - 10.10.100.200:22122
+file:
+  base-url: http://10.1.81.1:8888/
 spring:
   application:
     name: file-server
@@ -86,14 +96,4 @@ mybatis:
   type-aliases-package: com.usoftchina.smartschool.file.po
   mapper-locations: classpath:mapper/*.xml
 auth:
-  public-key: auth/pub.key
-fdfs:
-  so-timeout: 1500
-  connect-timeout: 600
-  thumb-image:
-    width: 150
-    height: 150
-  tracker-list:
-    - 10.1.81.1:22122
-file:
-  base-url: http://10.1.81.1:8888/
+  public-key: auth/pub.key

+ 1 - 4
base-servers/file/file-server/src/main/resources/config/application-docker-prod.yml → base-servers/file/file-server-fdfs/src/main/resources/config/application-docker-prod.yml

@@ -4,7 +4,4 @@ eureka:
     prefer-ip-address: false
   client:
     serviceUrl:
-      defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@smartschool-eureka-server:9500/eureka/
-fdfs:
-  tracker-list:
-    - 10.10.100.200:22122
+      defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@smartschool-eureka-server:9500/eureka/

+ 0 - 0
base-servers/file/file-server/src/main/resources/config/application-docker.yml → base-servers/file/file-server-fdfs/src/main/resources/config/application-docker.yml


+ 0 - 0
base-servers/file/file-server/src/main/resources/logback-spring.xml → base-servers/file/file-server-fdfs/src/main/resources/logback-spring.xml


+ 41 - 0
base-servers/file/file-server-qcloud/pom.xml

@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>file</artifactId>
+        <groupId>com.usoftchina.smartschool</groupId>
+        <version>1.0.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>file-server-qcloud</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.usoftchina.smartschool</groupId>
+            <artifactId>file-server</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.usoftchina.smartschool</groupId>
+            <artifactId>file-storage-qcloud</artifactId>
+        </dependency>
+        <!-- test -->
+        <dependency>
+            <groupId>com.usoftchina.smartschool</groupId>
+            <artifactId>test-starter</artifactId>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>com.spotify</groupId>
+                <artifactId>docker-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 6 - 0
base-servers/file/file-server-qcloud/src/main/docker/Dockerfile

@@ -0,0 +1,6 @@
+FROM frolvlad/alpine-oraclejdk8:slim
+VOLUME /tmp
+ADD file-server-qcloud-1.0.0-SNAPSHOT.jar app.jar
+RUN sh -c 'touch /app.jar'
+ENV JAVA_OPTS=""
+ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]

+ 26 - 0
base-servers/file/file-server-qcloud/src/main/java/com/usoftchina/smartschool/file/qcloud/QCloudFileApplication.java

@@ -0,0 +1,26 @@
+package com.usoftchina.smartschool.file.qcloud;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
+import org.springframework.context.annotation.EnableMBeanExport;
+import org.springframework.jmx.support.RegistrationPolicy;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+/**
+ * @author yingp
+ * @date 2019/3/14
+ */
+@SpringBootApplication(scanBasePackages = "com.usoftchina.smartschool.file")
+@EnableEurekaClient
+@EnableTransactionManagement
+@MapperScan("com.usoftchina.smartschool.file.mapper")
+@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
+@EnableSwagger2
+public class QCloudFileApplication {
+    public static void main(String[] args) {
+        SpringApplication.run(QCloudFileApplication.class, args);
+    }
+}

+ 97 - 0
base-servers/file/file-server-qcloud/src/main/resources/application.yml

@@ -0,0 +1,97 @@
+qcloud:
+  cos:
+    secretId: AKIDngQ1QbKfRHxOcl6QxG5jIxcQ3YelYKUR
+    secretKey: ykGDn9HYAZkOs30oPxNcqgoyWvSnqfGf
+    region: ap-chengdu
+    bucketName: ydy-1258516134
+file:
+  base-url: https://${qcloud.cos.bucketName}.cos.${qcloud.cos.region}.myqcloud.com/
+spring:
+  application:
+    name: file-server
+  security:
+    user:
+      name: admin
+      password: select111***
+  rabbitmq:
+    host: 10.10.100.166
+    port: 5672
+    virtual-host: school
+    username: school
+    password: select123***
+  zipkin:
+    sender:
+      type: rabbit
+    locator:
+      discovery:
+        enabled: true
+  sleuth:
+    sampler:
+      probability: 1.0
+  datasource:
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    url: jdbc:mysql://10.10.100.166:3306/smart_campus?characterEncoding=utf-8&useSSL=false
+    username: root
+    password: select111***
+    hikari:
+      minimum-idle: 5
+      maximum-pool-size: 50
+      idle-timeout: 30000
+      max-lifetime: 1800000
+      connection-timeout: 30000
+  messages:
+    basename: i18n/messages
+  redis:
+    host: 10.10.100.166
+    port: 6379
+  jackson:
+    date-format: yyyy-MM-dd HH:mm:ss
+    time-zone: GMT+8
+  profiles:
+    active: dev
+  servlet:
+    multipart:
+      enabled: true
+      #20971520 ->  20M
+      max-file-size: 20971520
+      max-request-size: 20971520
+eureka:
+  instance:
+    leaseRenewalIntervalInSeconds: 10
+    health-check-url-path: /actuator/health
+    status-page-url-path: /actuator/info
+    prefer-ip-address: true
+    metadata-map:
+      user.name: ${spring.security.user.name}
+      user.password: ${spring.security.user.password}
+  client:
+    registryFetchIntervalSeconds: 5
+    serviceUrl:
+      defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@127.0.0.1:9500/eureka/
+server:
+  port: 9540
+  tomcat:
+    uri-encoding: UTF-8
+management:
+  endpoints:
+    web:
+      exposure:
+        include: "*"
+  endpoint:
+    health:
+      show-details: always
+    shutdown:
+      enabled: true
+    restart:
+      enabled: true
+info:
+  name: '@project.artifactId@'
+  description: '@project.description@'
+  version: '@project.version@'
+  spring-boot-version: '@spring.boot.version@'
+  spring-cloud-version: '@spring.cloud.version@'
+mybatis:
+  type-aliases-package: com.usoftchina.smartschool.file.po
+  mapper-locations: classpath:mapper/*.xml
+auth:
+  public-key: auth/pub.key

+ 7 - 0
base-servers/file/file-server-qcloud/src/main/resources/config/application-docker-prod.yml

@@ -0,0 +1,7 @@
+eureka:
+  instance:
+    hostname: smartschool-file-server
+    prefer-ip-address: false
+  client:
+    serviceUrl:
+      defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@smartschool-eureka-server:9500/eureka/

+ 131 - 0
base-servers/file/file-server-qcloud/src/main/resources/logback-spring.xml

@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+    <include resource="org/springframework/boot/logging/logback/base.xml" />
+    <jmxConfigurator/>
+
+    <!--
+    %m
+    输出代码中指定的消息
+    %p
+    输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
+    %r
+    输出自应用启动到输出该log信息耗费的毫秒数
+    %c
+    输出所属的类目,通常就是所在类的全名
+    %t
+    输出产生该日志事件的线程名
+    %n
+    输出一个回车换行符,Windows平台为“\r\n”,Unix平台为“\n”
+    %d
+    输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},
+    输出类似:2002年10月18日 22:10:28,921
+    %l
+    输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java:10)
+    -->
+
+    <springProperty scope="context" name="log.path" source="logging.path" defaultValue="/var/log/smartschool/file-server"/>
+    <springProperty scope="context" name="spring.application.name" source="spring.application.name" defaultValue="file-server"/>
+    <springProperty scope="context" name="spring.profiles.active" source="spring.profiles.active" defaultValue="dev"/>
+    <springProperty scope="context" name="common-pattern" source="logging.common-pattern" defaultValue="%d{yyyy-MM-dd HH:mm:ss.SSS}:[%5p] [%t:%r] [%C{1}:%M:%L] --> %m%n"/>
+    <springProperty scope="context" name="log.level.console" source="logging.level.console" defaultValue="INFO"/>
+    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="10.1.81.1:5000"/>
+
+    <contextName>${spring.application.name}-${spring.profiles.active}-logback</contextName>
+
+    <appender name="CONSOLE_APPENDER" class="ch.qos.logback.core.ConsoleAppender">
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>${log.level.console}</level>
+        </filter>
+        <encoder>
+            <pattern>${common-pattern}</pattern>
+        </encoder>
+    </appender>
+
+    <appender name="ROOT_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${log.path}/root.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${log.path}/%d{yyyy-MM}/root-%d{yyyy-MM-dd}-%i.log.gz</fileNamePattern>
+            <maxFileSize>128MB</maxFileSize>
+            <maxHistory>7</maxHistory>
+            <totalSizeCap>20GB</totalSizeCap>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${common-pattern}</pattern>
+        </encoder>
+    </appender>
+
+    <!-- Appender to log in a JSON format -->
+    <appender name="JSON_APPENDER" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
+        <destination>${log.destination}</destination>
+        <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
+            <providers>
+                <pattern>
+                    <pattern>
+                        {
+                        "severity": "%level",
+                        "service": "${spring.application.name:-}",
+                        "trace": "%X{X-B3-TraceId:-}",
+                        "span": "%X{X-B3-SpanId:-}",
+                        "parent": "%X{X-B3-ParentSpanId:-}",
+                        "exportable": "%X{X-Span-Export:-}",
+                        "pid": "${PID:-}",
+                        "thread": "%thread",
+                        "class": "%logger{40}",
+                        "rest": "%message"
+                        }
+                    </pattern>
+                </pattern>
+            </providers>
+        </encoder>
+    </appender>
+
+    <logger name="org.springframework" level="INFO"/>
+    <logger name="com.usoftchina.smartschool" level="INFO"/>
+
+    <springProfile name="dev">
+        <root level="INFO">
+            <appender-ref ref="CONSOLE_APPENDER"/>
+        </root>
+    </springProfile>
+
+    <springProfile name="test">
+        <root level="INFO">
+            <appender-ref ref="CONSOLE_APPENDER"/>
+            <appender-ref ref="ROOT_APPENDER"/>
+        </root>
+    </springProfile>
+
+    <springProfile name="docker">
+        <logger name="org.springframework" level="WARN"/>
+        <logger name="com.usoftchina.smartschool" level="WARN"/>
+        <root level="WARN">
+            <appender-ref ref="CONSOLE_APPENDER"/>
+            <appender-ref ref="JSON_APPENDER"/>
+        </root>
+    </springProfile>
+
+    <springProfile name="docker-dev">
+        <root level="INFO">
+            <appender-ref ref="CONSOLE_APPENDER"/>
+        </root>
+    </springProfile>
+
+    <springProfile name="docker-test">
+        <logger name="org.springframework" level="WARN"/>
+        <logger name="com.usoftchina.smartschool" level="WARN"/>
+        <root level="WARN">
+            <appender-ref ref="CONSOLE_APPENDER"/>
+            <appender-ref ref="JSON_APPENDER"/>
+        </root>
+    </springProfile>
+
+    <springProfile name="docker-prod">
+        <logger name="org.springframework" level="WARN"/>
+        <logger name="com.usoftchina.smartschool" level="WARN"/>
+        <root level="WARN">
+            <appender-ref ref="CONSOLE_APPENDER"/>
+            <appender-ref ref="JSON_APPENDER"/>
+        </root>
+    </springProfile>
+
+</configuration>

+ 2 - 19
base-servers/file/file-server/pom.xml

@@ -48,8 +48,8 @@
         </dependency>
 
         <dependency>
-            <groupId>com.github.tobato</groupId>
-            <artifactId>fastdfs-client</artifactId>
+            <groupId>com.usoftchina.smartschool</groupId>
+            <artifactId>file-storage</artifactId>
         </dependency>
         <dependency>
             <groupId>org.apache.commons</groupId>
@@ -68,23 +68,6 @@
             <groupId>net.logstash.logback</groupId>
             <artifactId>logstash-logback-encoder</artifactId>
         </dependency>
-        <!-- test -->
-        <dependency>
-            <groupId>com.usoftchina.smartschool</groupId>
-            <artifactId>test-starter</artifactId>
-        </dependency>
     </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.springframework.boot</groupId>
-                <artifactId>spring-boot-maven-plugin</artifactId>
-            </plugin>
-            <plugin>
-                <groupId>com.spotify</groupId>
-                <artifactId>docker-maven-plugin</artifactId>
-            </plugin>
-        </plugins>
-    </build>
 
 </project>

+ 5 - 12
base-servers/file/file-server/src/main/java/com/usoftchina/smartschool/file/controller/FileController.java

@@ -1,7 +1,5 @@
 package com.usoftchina.smartschool.file.controller;
 
-import com.github.tobato.fastdfs.domain.StorePath;
-import com.github.tobato.fastdfs.service.FastFileStorageClient;
 import com.usoftchina.smartschool.base.Result;
 import com.usoftchina.smartschool.exception.BizException;
 import com.usoftchina.smartschool.exception.ExceptionCode;
@@ -11,6 +9,7 @@ import com.usoftchina.smartschool.file.dto.FolderDTO;
 import com.usoftchina.smartschool.file.dto.FolderSaveDTO;
 import com.usoftchina.smartschool.file.po.FileInfo;
 import com.usoftchina.smartschool.file.service.FileInfoService;
+import com.usoftchina.smartschool.file.storage.FileStorageClient;
 import com.usoftchina.smartschool.utils.BeanMapper;
 import com.usoftchina.smartschool.utils.BizAssert;
 import com.usoftchina.smartschool.utils.CollectionUtils;
@@ -20,7 +19,6 @@ import io.swagger.annotations.ApiOperation;
 import org.apache.commons.compress.archivers.ArchiveOutputStream;
 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
 import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
-import org.apache.commons.io.IOUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.http.MediaType;
@@ -48,7 +46,7 @@ public class FileController {
     private FileInfoService fileService;
 
     @Autowired
-    private FastFileStorageClient storageClient;
+    private FileStorageClient storageClient;
     /**
      * 文件访问服务baseUrl
      *
@@ -127,9 +125,7 @@ public class FileController {
             if (null != info.getFullPath()) {
                 response.setHeader("Content-disposition",
                         "attachment; filename=" + URLEncoder.encode(info.getName(), "UTF-8"));
-                StorePath path = StorePath.praseFromUrl(info.getFullPath());
-                storageClient.downloadFile(path.getGroup(), path.getPath(),
-                        in -> IOUtils.copy(in, response.getOutputStream()));
+                storageClient.downloadFile(info.getFullPath(), response.getOutputStream());
             }
         }
     }
@@ -159,9 +155,7 @@ public class FileController {
             if (!StringUtils.isEmpty(info.getMime())) {
                 response.setContentType(info.getMime());
             }
-            StorePath path = StorePath.praseFromUrl(info.getFullPath());
-            storageClient.downloadFile(path.getGroup(), path.getPath(),
-                    in -> IOUtils.copy(in, response.getOutputStream()));
+            storageClient.downloadFile(info.getFullPath(), response.getOutputStream());
         } else {
             // 无法直接查看的文件,下载到客户端
             download(info.getId(), response);
@@ -248,8 +242,7 @@ public class FileController {
             }
         } else {
             out.putArchiveEntry(new ZipArchiveEntry(directory + info.getName()));
-            StorePath path = StorePath.praseFromUrl(info.getFullPath());
-            storageClient.downloadFile(path.getGroup(), path.getPath(), in -> IOUtils.copy(in, out));
+            storageClient.downloadFile(info.getFullPath(), out);
             out.closeArchiveEntry();
         }
     }

+ 15 - 21
base-servers/file/file-server/src/main/java/com/usoftchina/smartschool/file/po/FileInfo.java

@@ -1,14 +1,14 @@
 package com.usoftchina.smartschool.file.po;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.github.tobato.fastdfs.domain.StorePath;
-import com.github.tobato.fastdfs.service.FastFileStorageClient;
 import com.usoftchina.smartschool.base.entity.CommonBaseEntity;
 import com.usoftchina.smartschool.context.BaseContextHolder;
-import com.usoftchina.smartschool.file.constant.FileType;
-import com.usoftchina.smartschool.file.util.FileTypeUtils;
+import com.usoftchina.smartschool.file.storage.FileMetadata;
+import com.usoftchina.smartschool.file.storage.FileStorageClient;
+import com.usoftchina.smartschool.file.storage.util.FileType;
+import com.usoftchina.smartschool.file.storage.util.FileTypeUtils;
+import com.usoftchina.smartschool.file.storage.util.FilenameUtils;
 import com.usoftchina.smartschool.utils.StringUtils;
-import org.apache.commons.io.FilenameUtils;
 import org.springframework.web.multipart.MultipartFile;
 
 import java.io.IOException;
@@ -19,7 +19,7 @@ import java.util.Date;
  * @author yingp
  * @date 2018/9/29
  */
-public class FileInfo extends CommonBaseEntity implements Serializable{
+public class FileInfo extends CommonBaseEntity implements Serializable {
     /**
      * 文件夹id
      */
@@ -47,7 +47,8 @@ public class FileInfo extends CommonBaseEntity implements Serializable{
     private long size;
     /**
      * 类型
-     * @see com.usoftchina.smartschool.file.constant.FileType
+     *
+     * @see com.usoftchina.smartschool.file.storage.util.FileType
      */
     private String type;
 
@@ -211,7 +212,7 @@ public class FileInfo extends CommonBaseEntity implements Serializable{
         return info;
     }
 
-    public static Builder newFile(MultipartFile file){
+    public static Builder newFile(MultipartFile file) {
         return new Builder(file);
     }
 
@@ -227,7 +228,7 @@ public class FileInfo extends CommonBaseEntity implements Serializable{
         private long size;
         private String type;
         private MultipartFile multipartFile;
-        private FastFileStorageClient storageClient;
+        private FileStorageClient storageClient;
         private String baseUrl;
 
         public Builder(MultipartFile file) {
@@ -274,7 +275,7 @@ public class FileInfo extends CommonBaseEntity implements Serializable{
             return this;
         }
 
-        public Builder storeBy(FastFileStorageClient storageClient){
+        public Builder storeBy(FileStorageClient storageClient) {
             this.storageClient = storageClient;
             return this;
         }
@@ -284,18 +285,11 @@ public class FileInfo extends CommonBaseEntity implements Serializable{
             return this;
         }
 
-        public FileInfo build() throws IOException{
+        public FileInfo build() throws IOException {
             if (null != storageClient) {
-                StorePath storePath;
-                if (FileType.of(type) == FileType.IMAGE) {
-                    // 保存图片 + 生成缩略图
-                    storePath = storageClient.uploadImageAndCrtThumbImage(multipartFile.getInputStream(),
-                            size, ext, null);
-                } else {
-                    storePath = storageClient.uploadFile(multipartFile.getInputStream(),
-                            size, ext, null);
-                }
-                this.fullPath = StringUtils.nullIf(baseUrl) + storePath.getFullPath();
+                this.fullPath = StringUtils.nullIf(baseUrl) +
+                        storageClient.uploadFile(multipartFile.getInputStream(),
+                                new FileMetadata(mime, ext, size));
             }
 
             return new FileInfo(folderId, name, fullPath, mime, ext, type, size);

+ 0 - 13
base-servers/file/file-server/src/main/resources/config/application-dev.yml

@@ -1,13 +0,0 @@
-eureka:
-  instance:
-    leaseRenewalIntervalInSeconds: 10
-    health-check-url-path: /actuator/health
-    status-page-url-path: /actuator/info
-    prefer-ip-address: true
-    metadata-map:
-      user.name: ${spring.security.user.name}
-      user.password: ${spring.security.user.password}
-  client:
-    registryFetchIntervalSeconds: 5
-    serviceUrl:
-      defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@127.0.0.1:9500/eureka/

+ 0 - 12
base-servers/file/file-server/src/main/resources/config/application-docker-dev.yml

@@ -1,12 +0,0 @@
-eureka:
-  instance:
-    hostname: saas-file-server-dev
-    prefer-ip-address: false
-  client:
-    serviceUrl:
-      defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@saas-eureka-server-dev:8510/eureka/
-spring:
-  rabbitmq:
-    virtual-host: dev
-server:
-  port: 8650

+ 0 - 12
base-servers/file/file-server/src/main/resources/config/application-docker-test.yml

@@ -1,12 +0,0 @@
-eureka:
-  instance:
-    hostname: saas-file-server-test
-    prefer-ip-address: false
-  client:
-    serviceUrl:
-      defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@saas-eureka-server-test:8515/eureka/
-spring:
-  rabbitmq:
-    virtual-host: test
-server:
-  port: 8655

+ 0 - 0
base-servers/file/file-server/src/main/resources/i18n/messages_en_US.properties


+ 0 - 0
base-servers/file/file-server/src/main/resources/i18n/messages_zh_CN.properties


+ 24 - 0
base-servers/file/file-storage-fdfs/pom.xml

@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>file</artifactId>
+        <groupId>com.usoftchina.smartschool</groupId>
+        <version>1.0.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>file-storage-fdfs</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.github.tobato</groupId>
+            <artifactId>fastdfs-client</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.usoftchina.smartschool</groupId>
+            <artifactId>file-storage</artifactId>
+        </dependency>
+    </dependencies>
+</project>

+ 21 - 0
base-servers/file/file-storage-fdfs/src/main/java/com/usoftchina/smartschool/file/storage/fdfs/FdfsConfig.java

@@ -0,0 +1,21 @@
+package com.usoftchina.smartschool.file.storage.fdfs;
+
+import com.github.tobato.fastdfs.FdfsClientConfig;
+import com.usoftchina.smartschool.file.storage.FileStorageClient;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+
+/**
+ * @author yingp
+ * @date 2019/3/14
+ */
+@Configuration
+@Import(FdfsClientConfig.class)
+public class FdfsConfig {
+
+    @Bean
+    public FileStorageClient fileStorageClient() {
+        return new FdfsFileStorageClient();
+    }
+}

+ 50 - 0
base-servers/file/file-storage-fdfs/src/main/java/com/usoftchina/smartschool/file/storage/fdfs/FdfsFileStorageClient.java

@@ -0,0 +1,50 @@
+package com.usoftchina.smartschool.file.storage.fdfs;
+
+import com.github.tobato.fastdfs.domain.StorePath;
+import com.github.tobato.fastdfs.service.FastFileStorageClient;
+import com.usoftchina.smartschool.file.storage.FileMetadata;
+import com.usoftchina.smartschool.file.storage.FileStorageClient;
+import com.usoftchina.smartschool.file.storage.util.FileType;
+import com.usoftchina.smartschool.file.storage.util.FileTypeUtils;
+import org.apache.commons.io.IOUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * @author yingp
+ * @date 2019/3/14
+ */
+public class FdfsFileStorageClient implements FileStorageClient{
+
+    @Autowired
+    private FastFileStorageClient storageClient;
+
+    @Override
+    public String uploadFile(InputStream inputStream, FileMetadata metadata) {
+        FileType type = FileTypeUtils.getFileType(metadata.getMime(), metadata.getExt());
+        StorePath storePath;
+        if (FileType.IMAGE == type) {
+            // 保存图片 + 生成缩略图
+            storePath = storageClient.uploadImageAndCrtThumbImage(inputStream, metadata.getSize(),
+                    metadata.getExt(), null);
+        } else {
+            storePath = storageClient.uploadFile(inputStream, metadata.getSize(),
+                    metadata.getExt(), null);
+        }
+        return storePath.getFullPath();
+    }
+
+    @Override
+    public void deleteFile(String filePath) {
+        storageClient.deleteFile(filePath);
+    }
+
+    @Override
+    public void downloadFile(String filePath, OutputStream out) throws IOException{
+        StorePath path = StorePath.praseFromUrl(filePath);
+        storageClient.downloadFile(path.getGroup(), path.getPath(), in -> IOUtils.copy(in, out));
+    }
+}

+ 3 - 0
base-servers/file/file-storage-fdfs/src/main/resources/META-INF/spring.factories

@@ -0,0 +1,3 @@
+# Auto Configuration
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+com.usoftchina.smartschool.file.storage.fdfs.FdfsConfig

+ 35 - 0
base-servers/file/file-storage-qcloud/pom.xml

@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>file</artifactId>
+        <groupId>com.usoftchina.smartschool</groupId>
+        <version>1.0.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>file-storage-qcloud</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.qcloud</groupId>
+            <artifactId>cos_api</artifactId>
+            <version>5.4.10</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-log4j12</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.usoftchina.smartschool</groupId>
+            <artifactId>file-storage</artifactId>
+        </dependency>
+    </dependencies>
+</project>

+ 81 - 0
base-servers/file/file-storage-qcloud/src/main/java/com/usoftchina/smartschool/file/storage/qcloud/COSFileStorageClient.java

@@ -0,0 +1,81 @@
+package com.usoftchina.smartschool.file.storage.qcloud;
+
+import com.qcloud.cos.COSClient;
+import com.qcloud.cos.ClientConfig;
+import com.qcloud.cos.auth.BasicCOSCredentials;
+import com.qcloud.cos.auth.COSCredentials;
+import com.qcloud.cos.model.COSObject;
+import com.qcloud.cos.model.ObjectMetadata;
+import com.qcloud.cos.region.Region;
+import com.qcloud.cos.utils.IOUtils;
+import com.usoftchina.smartschool.file.storage.FileMetadata;
+import com.usoftchina.smartschool.file.storage.FileStorageClient;
+import org.springframework.util.StringUtils;
+
+import javax.annotation.PreDestroy;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.UUID;
+
+/**
+ * @author yingp
+ * @date 2019/3/14
+ */
+public class COSFileStorageClient implements FileStorageClient {
+
+    private final CosProperties cosProperties;
+    private final COSClient client;
+
+    public COSFileStorageClient(CosProperties cosProperties) {
+        this.cosProperties = cosProperties;
+        this.client = initCOSClient();
+    }
+
+    private COSClient initCOSClient() {
+        // 1 初始化用户身份信息
+        COSCredentials cred = new BasicCOSCredentials(cosProperties.getSecretId(),
+                cosProperties.getSecretKey());
+        // 2 设置bucket的区域
+        ClientConfig clientConfig = new ClientConfig(new Region(cosProperties.getRegion()));
+        // 3 生成 cos 客户端。
+        return new COSClient(cred, clientConfig);
+    }
+
+    @Override
+    public String uploadFile(InputStream inputStream, FileMetadata metadata) {
+        ObjectMetadata objectMetadata = new ObjectMetadata();
+        objectMetadata.setContentLength(metadata.getSize());
+        if (!StringUtils.isEmpty(metadata.getMime())) {
+            objectMetadata.setContentType(metadata.getMime());
+        }
+        String filePath = generateDefaultFilePath() +
+                (StringUtils.isEmpty(metadata.getExt()) ? "" : ("." + metadata.getExt()));
+        client.putObject(cosProperties.getBucketName(), filePath, inputStream, objectMetadata);
+        return filePath;
+    }
+
+    private String generateDefaultFilePath() {
+        // 当天 + 随机串
+        return LocalDateTime.now().format(DateTimeFormatter.ISO_DATE) + "/" +
+                UUID.randomUUID().toString();
+    }
+
+    @Override
+    public void deleteFile(String filePath) {
+        client.deleteObject(cosProperties.getBucketName(), filePath);
+    }
+
+    @PreDestroy
+    public void shutdown() {
+        client.shutdown();
+    }
+
+    @Override
+    public void downloadFile(String filePath, OutputStream out) throws IOException {
+        COSObject object = client.getObject(cosProperties.getBucketName(), filePath);
+        IOUtils.copy(object.getObjectContent(), out);
+    }
+}

+ 58 - 0
base-servers/file/file-storage-qcloud/src/main/java/com/usoftchina/smartschool/file/storage/qcloud/CosProperties.java

@@ -0,0 +1,58 @@
+package com.usoftchina.smartschool.file.storage.qcloud;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * @author yingp
+ * @date 2019/3/14
+ */
+@ConfigurationProperties(CosProperties.PREFIX)
+public class CosProperties {
+    public static final String PREFIX = "qcloud.cos";
+
+    /**
+     * 秘钥
+     */
+    private String secretId;
+    private String secretKey;
+    /**
+     * 所属地域
+     */
+    private String region;
+    /**
+     * 存储桶名称
+     */
+    private String bucketName;
+
+    public String getSecretId() {
+        return secretId;
+    }
+
+    public void setSecretId(String secretId) {
+        this.secretId = secretId;
+    }
+
+    public String getSecretKey() {
+        return secretKey;
+    }
+
+    public void setSecretKey(String secretKey) {
+        this.secretKey = secretKey;
+    }
+
+    public String getRegion() {
+        return region;
+    }
+
+    public void setRegion(String region) {
+        this.region = region;
+    }
+
+    public String getBucketName() {
+        return bucketName;
+    }
+
+    public void setBucketName(String bucketName) {
+        this.bucketName = bucketName;
+    }
+}

+ 24 - 0
base-servers/file/file-storage-qcloud/src/main/java/com/usoftchina/smartschool/file/storage/qcloud/QCloudConfig.java

@@ -0,0 +1,24 @@
+package com.usoftchina.smartschool.file.storage.qcloud;
+
+import com.usoftchina.smartschool.file.storage.FileStorageClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author yingp
+ * @date 2019/3/14
+ */
+@Configuration
+@EnableConfigurationProperties(CosProperties.class)
+public class QCloudConfig {
+
+    @Autowired
+    private CosProperties cosProperties;
+
+    @Bean
+    public FileStorageClient fileStorageClient() {
+        return new COSFileStorageClient(cosProperties);
+    }
+}

+ 3 - 0
base-servers/file/file-storage-qcloud/src/main/resources/META-INF/spring.factories

@@ -0,0 +1,3 @@
+# Auto Configuration
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+com.usoftchina.smartschool.file.storage.qcloud.QCloudConfig

+ 37 - 0
base-servers/file/file-storage-qcloud/src/test/java/com/usoftchina/smartschool/file/storage/qcloud/COSFileStorageClientTest.java

@@ -0,0 +1,37 @@
+package com.usoftchina.smartschool.file.storage.qcloud;
+
+import com.usoftchina.smartschool.file.storage.FileMetadata;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * @author yingp
+ * @date 2019/3/14
+ */
+public class COSFileStorageClientTest {
+    private static COSFileStorageClient getClient() {
+        CosProperties properties = new CosProperties();
+        properties.setSecretId("AKIDngQ1QbKfRHxOcl6QxG5jIxcQ3YelYKUR");
+        properties.setSecretKey("ykGDn9HYAZkOs30oPxNcqgoyWvSnqfGf");
+        properties.setRegion("ap-chengdu");
+        properties.setBucketName("ydy-1258516134");
+        return new COSFileStorageClient(properties);
+    }
+
+    public static void main(String[] args) throws IOException{
+        RandomTextFile file = new RandomTextFile();
+        COSFileStorageClient client = getClient();
+        try {
+            String filePath = client.uploadFile(file.getInputStream(), new FileMetadata(null,
+                    file.getFileExtName(), file.getFileSize()));
+            System.out.println(filePath);
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            client.downloadFile(filePath, out);
+            assert file.getText().equals(out.toString());
+            client.deleteFile(filePath);
+        } finally {
+            client.shutdown();
+        }
+    }
+}

+ 49 - 0
base-servers/file/file-storage-qcloud/src/test/java/com/usoftchina/smartschool/file/storage/qcloud/RandomTextFile.java

@@ -0,0 +1,49 @@
+package com.usoftchina.smartschool.file.storage.qcloud;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.UUID;
+
+/**
+ * @author yingp
+ * @date 2018/11/9
+ */
+public class RandomTextFile {
+    private String text;
+
+    private InputStream inputStream;
+
+    private long fileSize;
+
+    private String fileExtName = "text";
+
+    public RandomTextFile() {
+        this(UUID.randomUUID().toString());
+    }
+
+    public RandomTextFile(String text) {
+        this.text = text;
+        this.fileSize = text.getBytes().length;
+    }
+
+    public String getText() {
+        return text;
+    }
+
+    public InputStream getInputStream() {
+        this.inputStream = new ByteArrayInputStream(text.getBytes());
+        return inputStream;
+    }
+
+    public long getFileSize() {
+        return fileSize;
+    }
+
+    public String getFileExtName() {
+        return fileExtName;
+    }
+
+    public byte[] toByte() {
+        return this.text.getBytes();
+    }
+}

+ 15 - 0
base-servers/file/file-storage/pom.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>file</artifactId>
+        <groupId>com.usoftchina.smartschool</groupId>
+        <version>1.0.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>file-storage</artifactId>
+
+
+</project>

+ 44 - 0
base-servers/file/file-storage/src/main/java/com/usoftchina/smartschool/file/storage/FileMetadata.java

@@ -0,0 +1,44 @@
+package com.usoftchina.smartschool.file.storage;
+
+/**
+ * @author yingp
+ * @date 2019/3/14
+ */
+public class FileMetadata {
+    private String mime;
+    private String ext;
+    private long size;
+
+    public FileMetadata() {
+    }
+
+    public FileMetadata(String mime, String ext, long size) {
+        this.mime = mime;
+        this.ext = ext;
+        this.size = size;
+    }
+
+    public String getMime() {
+        return mime;
+    }
+
+    public void setMime(String mime) {
+        this.mime = mime;
+    }
+
+    public String getExt() {
+        return ext;
+    }
+
+    public void setExt(String ext) {
+        this.ext = ext;
+    }
+
+    public long getSize() {
+        return size;
+    }
+
+    public void setSize(long size) {
+        this.size = size;
+    }
+}

+ 39 - 0
base-servers/file/file-storage/src/main/java/com/usoftchina/smartschool/file/storage/FileStorageClient.java

@@ -0,0 +1,39 @@
+package com.usoftchina.smartschool.file.storage;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * 文件存储标准接口
+ *
+ * @author yingp
+ * @date 2019/3/14
+ */
+public interface FileStorageClient {
+
+    /**
+     * 上传文件
+     *
+     * @param inputStream
+     * @param metadata
+     * @return
+     */
+    String uploadFile(InputStream inputStream, FileMetadata metadata);
+
+    /**
+     * 删除文件
+     *
+     * @param filePath 文件路径 / 文件唯一标志
+     */
+    void deleteFile(String filePath);
+
+    /**
+     * 下载文件
+     *
+     * @param filePath 文件路径 / 文件唯一标志
+     * @param out
+     * @throws IOException
+     */
+    void downloadFile(String filePath, OutputStream out) throws IOException;
+}

+ 1 - 1
base-servers/file/file-server/src/main/java/com/usoftchina/smartschool/file/constant/FileType.java → base-servers/file/file-storage/src/main/java/com/usoftchina/smartschool/file/storage/util/FileType.java

@@ -1,4 +1,4 @@
-package com.usoftchina.smartschool.file.constant;
+package com.usoftchina.smartschool.file.storage.util;
 
 /**
  * @author yingp

+ 3 - 6
base-servers/file/file-server/src/main/java/com/usoftchina/smartschool/file/util/FileTypeUtils.java → base-servers/file/file-storage/src/main/java/com/usoftchina/smartschool/file/storage/util/FileTypeUtils.java

@@ -1,7 +1,4 @@
-package com.usoftchina.smartschool.file.util;
-
-import com.usoftchina.smartschool.file.constant.FileType;
-import com.usoftchina.smartschool.utils.StringUtils;
+package com.usoftchina.smartschool.file.storage.util;
 
 /**
  * @author yingp
@@ -25,7 +22,7 @@ public class FileTypeUtils {
     }
 
     public static FileType getFileTypeByMime(String mime) {
-        if (!StringUtils.isEmpty(mime)) {
+        if (null != mime && !mime.isEmpty()) {
             if (mime.startsWith("image/")) {
                 return FileType.IMAGE;
             }
@@ -56,7 +53,7 @@ public class FileTypeUtils {
     }
 
     public static FileType getFileTypeByExtension(String ext) {
-        if (!StringUtils.isEmpty(ext)) {
+        if (null != ext && !ext.isEmpty()) {
             switch (ext) {
                 case "gif":
                 case "jpeg":

+ 97 - 0
base-servers/file/file-storage/src/main/java/com/usoftchina/smartschool/file/storage/util/FilenameUtils.java

@@ -0,0 +1,97 @@
+package com.usoftchina.smartschool.file.storage.util;
+
+/**
+ * @author yingp
+ * @date 2019/3/14
+ */
+public class FilenameUtils {
+
+    /**
+     * The extension separator character.
+     * @since 1.4
+     */
+    public static final char EXTENSION_SEPARATOR = '.';
+
+    /**
+     * The Unix separator character.
+     */
+    private static final char UNIX_SEPARATOR = '/';
+
+    /**
+     * The Windows separator character.
+     */
+    private static final char WINDOWS_SEPARATOR = '\\';
+
+    /**
+     * Gets the extension of a filename.
+     * <p>
+     * This method returns the textual part of the filename after the last dot.
+     * There must be no directory separator after the dot.
+     * <pre>
+     * foo.txt      --> "txt"
+     * a/b/c.jpg    --> "jpg"
+     * a/b.txt/c    --> ""
+     * a/b/c        --> ""
+     * </pre>
+     * <p>
+     * The output will be the same irrespective of the machine that the code is running on.
+     *
+     * @param filename the filename to retrieve the extension of.
+     * @return the extension of the file or an empty string if none exists or {@code null}
+     * if the filename is {@code null}.
+     */
+    public static String getExtension(String filename) {
+        if (filename == null) {
+            return null;
+        }
+        int index = indexOfExtension(filename);
+        if (index == -1) {
+            return "";
+        } else {
+            return filename.substring(index + 1);
+        }
+    }
+
+    /**
+     * Returns the index of the last extension separator character, which is a dot.
+     * <p>
+     * This method also checks that there is no directory separator after the last dot.
+     * To do this it uses {@link #indexOfLastSeparator(String)} which will
+     * handle a file in either Unix or Windows format.
+     * <p>
+     * The output will be the same irrespective of the machine that the code is running on.
+     *
+     * @param filename  the filename to find the last path separator in, null returns -1
+     * @return the index of the last separator character, or -1 if there
+     * is no such character
+     */
+    public static int indexOfExtension(String filename) {
+        if (filename == null) {
+            return -1;
+        }
+        int extensionPos = filename.lastIndexOf(EXTENSION_SEPARATOR);
+        int lastSeparator = indexOfLastSeparator(filename);
+        return lastSeparator > extensionPos ? -1 : extensionPos;
+    }
+
+    /**
+     * Returns the index of the last directory separator character.
+     * <p>
+     * This method will handle a file in either Unix or Windows format.
+     * The position of the last forward or backslash is returned.
+     * <p>
+     * The output will be the same irrespective of the machine that the code is running on.
+     *
+     * @param filename  the filename to find the last path separator in, null returns -1
+     * @return the index of the last separator character, or -1 if there
+     * is no such character
+     */
+    public static int indexOfLastSeparator(String filename) {
+        if (filename == null) {
+            return -1;
+        }
+        int lastUnixPos = filename.lastIndexOf(UNIX_SEPARATOR);
+        int lastWindowsPos = filename.lastIndexOf(WINDOWS_SEPARATOR);
+        return Math.max(lastUnixPos, lastWindowsPos);
+    }
+}

+ 5 - 0
base-servers/file/pom.xml

@@ -15,6 +15,11 @@
         <module>file-api</module>
         <module>file-dto</module>
         <module>file-server</module>
+        <module>file-server-qcloud</module>
+        <module>file-storage-fdfs</module>
+        <module>file-storage-qcloud</module>
+        <module>file-storage</module>
+        <module>file-server-fdfs</module>
     </modules>
 
 

+ 20 - 0
pom.xml

@@ -283,6 +283,26 @@
                 <artifactId>device-sdk-dahua</artifactId>
                 <version>${project.release.version}</version>
             </dependency>
+            <dependency>
+                <groupId>com.usoftchina.smartschool</groupId>
+                <artifactId>file-server</artifactId>
+                <version>${project.release.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.usoftchina.smartschool</groupId>
+                <artifactId>file-storage</artifactId>
+                <version>${project.release.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.usoftchina.smartschool</groupId>
+                <artifactId>file-storage-fdfs</artifactId>
+                <version>${project.release.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.usoftchina.smartschool</groupId>
+                <artifactId>file-storage-qcloud</artifactId>
+                <version>${project.release.version}</version>
+            </dependency>
             <!-- file upload -->
             <dependency>
                 <groupId>io.github.openfeign.form</groupId>