瀏覽代碼

文件上传服务

master
qiubh 2 週之前
當前提交
8fa10e8b34
共有 53 個文件被更改,包括 2255 次插入0 次删除
  1. 二進制
      .gradle/7.2-rc-2/dependencies-accessors/dependencies-accessors.lock
  2. 0
    0
      .gradle/7.2-rc-2/dependencies-accessors/gc.properties
  3. 二進制
      .gradle/7.2-rc-2/executionHistory/executionHistory.bin
  4. 二進制
      .gradle/7.2-rc-2/executionHistory/executionHistory.lock
  5. 二進制
      .gradle/7.2-rc-2/fileChanges/last-build.bin
  6. 二進制
      .gradle/7.2-rc-2/fileHashes/fileHashes.bin
  7. 二進制
      .gradle/7.2-rc-2/fileHashes/fileHashes.lock
  8. 二進制
      .gradle/7.2-rc-2/fileHashes/resourceHashesCache.bin
  9. 0
    0
      .gradle/7.2-rc-2/gc.properties
  10. 二進制
      .gradle/buildOutputCleanup/buildOutputCleanup.lock
  11. 2
    0
      .gradle/buildOutputCleanup/cache.properties
  12. 二進制
      .gradle/buildOutputCleanup/outputFiles.bin
  13. 二進制
      .gradle/checksums/checksums.lock
  14. 二進制
      .gradle/checksums/md5-checksums.bin
  15. 二進制
      .gradle/checksums/sha1-checksums.bin
  16. 0
    0
      .gradle/vcs-1/gc.properties
  17. 8
    0
      .idea/.gitignore
  18. 1
    0
      .idea/.name
  19. 15
    0
      .idea/compiler.xml
  20. 17
    0
      .idea/gradle.xml
  21. 20
    0
      .idea/jarRepositories.xml
  22. 10
    0
      .idea/misc.xml
  23. 8
    0
      .idea/modules.xml
  24. 8
    0
      .idea/modules/file_system.main.iml
  25. 6
    0
      .idea/vcs.xml
  26. 2
    0
      README.md
  27. 40
    0
      build.gradle
  28. 二進制
      gradle/wrapper/gradle-wrapper.jar
  29. 5
    0
      gradle/wrapper/gradle-wrapper.properties
  30. 185
    0
      gradlew
  31. 104
    0
      gradlew.bat
  32. 1
    0
      settings.gradle
  33. 13
    0
      src/main/java/com/taiji/system/FileSystemApplication.java
  34. 50
    0
      src/main/java/com/taiji/system/config/SwaggerConfig.java
  35. 74
    0
      src/main/java/com/taiji/system/controller/MinIoController.java
  36. 48
    0
      src/main/java/com/taiji/system/enums/OssType.java
  37. 42
    0
      src/main/java/com/taiji/system/enums/ResultStatusEnum.java
  38. 22
    0
      src/main/java/com/taiji/system/oss/ChannelModel.java
  39. 48
    0
      src/main/java/com/taiji/system/oss/ChannelProperties.java
  40. 24
    0
      src/main/java/com/taiji/system/oss/ChannelPropertiesModel.java
  41. 45
    0
      src/main/java/com/taiji/system/oss/FileUrlVo.java
  42. 728
    0
      src/main/java/com/taiji/system/oss/MinIoContentType.java
  43. 358
    0
      src/main/java/com/taiji/system/oss/MinIoTemplate.java
  44. 39
    0
      src/main/java/com/taiji/system/oss/MinioConfiguration.java
  45. 30
    0
      src/main/java/com/taiji/system/oss/OssFile.java
  46. 93
    0
      src/main/java/com/taiji/system/oss/OssProperties.java
  47. 16
    0
      src/main/java/com/taiji/system/util/GlobalException.java
  48. 44
    0
      src/main/java/com/taiji/system/util/GlobalExceptionHandle.java
  49. 98
    0
      src/main/java/com/taiji/system/util/ResultWrapper.java
  50. 9
    0
      src/main/resources/application-dev.yml
  51. 18
    0
      src/main/resources/application-prod.yml
  52. 11
    0
      src/main/resources/application.yml
  53. 13
    0
      src/test/java/com/taiji/system/FileSystemApplicationTests.java

二進制
.gradle/7.2-rc-2/dependencies-accessors/dependencies-accessors.lock 查看文件


+ 0
- 0
.gradle/7.2-rc-2/dependencies-accessors/gc.properties 查看文件


二進制
.gradle/7.2-rc-2/executionHistory/executionHistory.bin 查看文件


二進制
.gradle/7.2-rc-2/executionHistory/executionHistory.lock 查看文件


二進制
.gradle/7.2-rc-2/fileChanges/last-build.bin 查看文件


二進制
.gradle/7.2-rc-2/fileHashes/fileHashes.bin 查看文件


二進制
.gradle/7.2-rc-2/fileHashes/fileHashes.lock 查看文件


二進制
.gradle/7.2-rc-2/fileHashes/resourceHashesCache.bin 查看文件


+ 0
- 0
.gradle/7.2-rc-2/gc.properties 查看文件


二進制
.gradle/buildOutputCleanup/buildOutputCleanup.lock 查看文件


+ 2
- 0
.gradle/buildOutputCleanup/cache.properties 查看文件

@@ -0,0 +1,2 @@
#Mon May 12 16:16:27 CST 2025
gradle.version=7.2-rc-2

二進制
.gradle/buildOutputCleanup/outputFiles.bin 查看文件


二進制
.gradle/checksums/checksums.lock 查看文件


二進制
.gradle/checksums/md5-checksums.bin 查看文件


二進制
.gradle/checksums/sha1-checksums.bin 查看文件


+ 0
- 0
.gradle/vcs-1/gc.properties 查看文件


+ 8
- 0
.idea/.gitignore 查看文件

@@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

+ 1
- 0
.idea/.name 查看文件

@@ -0,0 +1 @@
file_system

+ 15
- 0
.idea/compiler.xml 查看文件

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile name="Gradle Imported" enabled="true">
<outputRelativeToContentRoot value="true" />
<processorPath useClasspath="false">
<entry name="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-configuration-processor/2.3.7.RELEASE/720a39aaa5028de9458377cb014c56e2a3988eda/spring-boot-configuration-processor-2.3.7.RELEASE.jar" />
</processorPath>
<module name="file_system.main" />
</profile>
</annotationProcessing>
<bytecodeTargetLevel target="1.8" />
</component>
</project>

+ 17
- 0
.idea/gradle.xml 查看文件

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="#JAVA_HOME" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>

+ 20
- 0
.idea/jarRepositories.xml 查看文件

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="MavenRepo" />
<option name="name" value="MavenRepo" />
<option name="url" value="https://repo.maven.apache.org/maven2/" />
</remote-repository>
</component>
</project>

+ 10
- 0
.idea/misc.xml 查看文件

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="FrameworkDetectionExcludesConfiguration">
<file type="web" url="file://$PROJECT_DIR$" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="11" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

+ 8
- 0
.idea/modules.xml 查看文件

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/modules/file_system.main.iml" filepath="$PROJECT_DIR$/.idea/modules/file_system.main.iml" />
</modules>
</component>
</project>

+ 8
- 0
.idea/modules/file_system.main.iml 查看文件

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="AdditionalModuleElements">
<content url="file://$MODULE_DIR$/../../build/generated/sources/annotationProcessor/java/main">
<sourceFolder url="file://$MODULE_DIR$/../../build/generated/sources/annotationProcessor/java/main" isTestSource="false" generated="true" />
</content>
</component>
</module>

+ 6
- 0
.idea/vcs.xml 查看文件

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

+ 2
- 0
README.md 查看文件

@@ -0,0 +1,2 @@
# 文件管理系统


+ 40
- 0
build.gradle 查看文件

@@ -0,0 +1,40 @@
plugins {
id 'org.springframework.boot' version '2.3.7.RELEASE'
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
id 'java'
}

group = 'com.taiji'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
mavenCentral()
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
implementation group: 'com.alibaba', name: 'fastjson', version: '2.0.4'
runtimeOnly 'mysql:mysql-connector-java'
// https://mvnrepository.com/artifact/cn.hutool/hutool-all
implementation group: 'cn.hutool', name: 'hutool-all', version: '5.8.10'
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
// https://mvnrepository.com/artifact/io.minio/minio
// compile('io.minio:minio:8.4.5') {
// exclude module: "okhttp"
// }
implementation 'io.minio:minio:8.4.5'
// https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp
implementation group: 'com.squareup.okhttp3', name: 'okhttp', version: '4.10.0'
// https://mvnrepository.com/artifact/io.springfox/springfox-boot-starter
implementation group: 'io.springfox', name: 'springfox-boot-starter', version: '3.0.0'
implementation 'org.springframework:spring-test:5.3.10'

}

test {
useJUnitPlatform()
}

二進制
gradle/wrapper/gradle-wrapper.jar 查看文件


+ 5
- 0
gradle/wrapper/gradle-wrapper.properties 查看文件

@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https://mirrors.cloud.tencent.com/gradle/gradle-7.2-rc-2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

+ 185
- 0
gradlew 查看文件

@@ -0,0 +1,185 @@
#!/usr/bin/env sh

#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################

# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null

APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`

# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"

warn () {
echo "$*"
}

die () {
echo
echo "$*"
echo
exit 1
}

# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac

CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar


# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi

# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi

# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi

# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`

# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option

if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi

# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`

# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"

exec "$JAVACMD" "$@"

+ 104
- 0
gradlew.bat 查看文件

@@ -0,0 +1,104 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem

@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################

@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal

set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%

@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi

@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"

@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome

set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe

if exist "%JAVA_EXE%" goto init

echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:init
@rem Get command-line arguments, handling Windows variants

if not "%OS%" == "Windows_NT" goto win9xME_args

:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2

:win9xME_args_slurp
if "x%~1" == "x" goto execute

set CMD_LINE_ARGS=%*

:execute
@rem Setup the command line

set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar


@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%

:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd

:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1

:mainEnd
if "%OS%"=="Windows_NT" endlocal

:omega

+ 1
- 0
settings.gradle 查看文件

@@ -0,0 +1 @@
rootProject.name = 'file_system'

+ 13
- 0
src/main/java/com/taiji/system/FileSystemApplication.java 查看文件

@@ -0,0 +1,13 @@
package com.taiji.system;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class FileSystemApplication {

public static void main(String[] args) {
SpringApplication.run(FileSystemApplication.class, args);
}

}

+ 50
- 0
src/main/java/com/taiji/system/config/SwaggerConfig.java 查看文件

@@ -0,0 +1,50 @@
package com.taiji.system.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

/***
* <p>
* swagger 3.0 配置类
* </p>
* @author hou yi
* @date 2023/1/29 14:12
**/
@Configuration
public class SwaggerConfig {

@Value("${swagger.enabled:false}")
private Boolean enabled;

@Bean
public Docket createRestApi() {
// v3 与 v2 不同
return new Docket(DocumentationType.OAS_30)
// 是否开启 swagger
.enable(enabled)
// api 信息
.apiInfo(apiInfo())
.select()
// 设置扫描路径
.apis(RequestHandlerSelectors.basePackage("com.taiji.system.controller"))
.build()
;
}

private ApiInfo apiInfo() {
return new ApiInfoBuilder()
// 文档标题
.title("文件管理系统接口文档")
// 文档描述
.description("文件管理系统接口说明")
// 版本号
.version("1,0.0")
.build();
}
}

+ 74
- 0
src/main/java/com/taiji/system/controller/MinIoController.java 查看文件

@@ -0,0 +1,74 @@
package com.taiji.system.controller;

import com.taiji.system.oss.FileUrlVo;
import com.taiji.system.oss.MinIoTemplate;
import com.taiji.system.oss.OssFile;
import com.taiji.system.util.ResultWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

/***
* <p>
* 文件管理控制器
* </p>
* @author hou yi
* @date 2022/11/21 9:47
**/
@RestController
@RequestMapping("minIo")
@Api(tags = "MinIo 文件管理")
public class MinIoController {

@Resource
private MinIoTemplate minIoTemplate;

@PostMapping("upload")
@ApiOperation("上传文件")
public ResultWrapper<OssFile> upload(@ApiParam("上传的文件") @RequestPart() MultipartFile file,
@ApiParam("目标桶名称") @RequestParam(required = false) String bucket,
@ApiParam("业务标识") @RequestParam(required = false) String busCode) {
// 文件上传
return ResultWrapper.success(minIoTemplate.putObject(file, bucket, file.getOriginalFilename(), true, busCode));
}

@PostMapping("channelUpload")
@ApiOperation("上传文件")
public ResultWrapper<OssFile> channelUpload(@ApiParam("上传的文件") @RequestPart() MultipartFile file,
@ApiParam("appId") @RequestParam(required = false) String appId,
@ApiParam("accessKey") @RequestParam(required = false) String accessKey) {
// 文件上传
return ResultWrapper.success(minIoTemplate.putObject(file, appId, accessKey, file.getOriginalFilename(), true));
}
@PostMapping("uploadUndoubled")
@ApiOperation("上传文件。相同文件名是直接覆盖")
public ResultWrapper<OssFile> uploadUndoubled(@ApiParam("上传的文件") @RequestPart() MultipartFile file,
@ApiParam("目标桶名称") @RequestParam(required = false) String bucket,
@ApiParam("业务标识") @RequestParam(required = false) String busCode) {
// 文件上传
return ResultWrapper.success(minIoTemplate.putObject(file, bucket, file.getOriginalFilename(), false, busCode));
}

@PostMapping("getDownloadUrl")
@ApiOperation("获取下载地址")
public ResultWrapper<FileUrlVo> getDownloadUrl(@ApiParam("目标桶名称") @RequestParam String bucket,
@ApiParam("目标文件路径") @RequestParam String ossFilePath) {
// 获取文件url
return ResultWrapper.success(minIoTemplate.getPresignedObjectUrl(bucket, ossFilePath));
}

@PostMapping("channelDownloadUrl")
@ApiOperation("获取下载地址")
public void channelDownloadUrl(@ApiParam("appId") @RequestParam String appId,
@ApiParam("accessKey") @RequestParam String accessKey,
HttpServletResponse response,
@ApiParam("目标文件路径") @RequestParam String ossFilePath) {
// 获取文件url
minIoTemplate.getPresignedObjectUrl(appId, accessKey, ossFilePath, response);
}
}

+ 48
- 0
src/main/java/com/taiji/system/enums/OssType.java 查看文件

@@ -0,0 +1,48 @@
package com.taiji.system.enums;

/***
* <p>
* OSS 对象存储类型
* </p>
* @author hou yi
* @date 2022/11/21 11:16
**/
public enum OssType {
/**
* Minio 对象存储
*/
MINIO("minio", 1),

/**
* 华为 OBS
*/
OBS("obs", 2),

/**
* 腾讯 COS
*/
COS("tencent", 3),

/**
* 阿里巴巴 SSO
*/
ALIBABA("alibaba", 4),
;

private final String code;

private final Integer type;

OssType(String code, Integer type) {
this.code = code;
this.type = type;
}

public String getCode() {
return code;
}

public Integer getType() {
return type;
}
}

+ 42
- 0
src/main/java/com/taiji/system/enums/ResultStatusEnum.java 查看文件

@@ -0,0 +1,42 @@
package com.taiji.system.enums;

/***
* <p>
* 统一返回值状态码
* </p>
* @author hou yi
* @date 2022/7/27 11:13
**/
public enum ResultStatusEnum {
/**
* 描述
*/
PARAMETER_ERROR(102, "参数错误"),
SUCCESS(200, "操作成功"),
GLOBAL_EXCEPTION(301, "统一异常处理"),
FAIL(500, "请求失败"),
;

/**
* 状态码
*/
private final Integer code;

/**
* 状态描述
*/
private final String message;

ResultStatusEnum(Integer code, String message) {
this.code = code;
this.message = message;
}

public Integer getCode() {
return code;
}

public String getMessage() {
return message;
}
}

+ 22
- 0
src/main/java/com/taiji/system/oss/ChannelModel.java 查看文件

@@ -0,0 +1,22 @@
package com.taiji.system.oss;

public class ChannelModel {
private String accessKey;
private String secretKey;

public String getAccessKey() {
return accessKey;
}

public void setAccessKey(String accessKey) {
this.accessKey = accessKey;
}

public String getSecretKey() {
return secretKey;
}

public void setSecretKey(String secretKey) {
this.secretKey = secretKey;
}
}

+ 48
- 0
src/main/java/com/taiji/system/oss/ChannelProperties.java 查看文件

@@ -0,0 +1,48 @@
package com.taiji.system.oss;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.taiji.system.enums.OssType;
import org.apache.commons.compress.utils.Lists;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.List;

/***
* <p>
*
* </p>
* @author hou yi
* @date 2022/11/21 11:02
**/
@Component
@ConfigurationProperties(prefix = "channel")
public class ChannelProperties {
private String channelProperties = "[{\"appId\": \"52188938\", \"data\": {\"accessKey\": \"ngHXrWydteDe2L17\",\"secretKey\": \"6nIZwuHr9d2kYnNUJXTVTRLKLAE6EvUO\",\"bucketName\": \"agent-issues\"}}, {\"appId\": \"52188919\", \"data\": {\"accessKey\": \"9ui9dR6auFRFlN8d\",\"secretKey\": \"BqVD75Sm0uiWI7OyZLl7jXkM80YpYZ6D\",\"bucketName\": \"agent-issues\"}}, {\"appId\": \"52188903\", \"data\": {\"accessKey\": \"ZgA0qBdjQVWK5Yge\",\"secretKey\": \"EllsTyWMmXOdktAcsw5A7J1PP4pqtFoJ\",\"bucketName\": \"agent-issues\"}}, {\"appId\": \"52188934\", \"data\": {\"accessKey\": \"GtdBfB1REv2rGjkx\",\"secretKey\": \"sH4ifK4cLYmrOoMArQ1ojA70gSZBdpfv\",\"bucketName\": \"agent-issues\"}}, {\"appId\": \"52188925\", \"data\": {\"accessKey\": \"W6eAN6cardfwTXU8\",\"secretKey\": \"T2KYEMj8zJcJFax40kdYflm66LZYfkiW\",\"bucketName\": \"agent-issues\"}}, {\"appId\": \"52106998\", \"data\": {\"accessKey\": \"zt2LEYdnJ3GEYDX9\",\"secretKey\": \"dGYME50FgvV07aa7cB8MZy3xrAyya9Lm\",\"bucketName\": \"agent-issues\"}}]";

public static void main(String[] args) {
String channelProperties = "[{\"appId\": \"52188938\", \"data\": {\"accessKey\": \"ngHXrWydteDe2L17\",\"SecretKey\": \"6nIZwuHr9d2kYnNUJXTVTRLKLAE6EvUO\",\"bucketName\": \"agent-issues\"}}, {\"appId\": \"52188919\", \"data\": {\"accessKey\": \"9ui9dR6auFRFlN8d\",\"SecretKey\": \"BqVD75Sm0uiWI7OyZLl7jXkM80YpYZ6D\",\"bucketName\": \"agent-issues\"}}, {\"appId\": \"52106998\", \"data\": {\"accessKey\": \"zt2LEYdnJ3GEYDX9\",\"SecretKey\": \"dGYME50FgvV07aa7cB8MZy3xrAyya9Lm\",\"bucketName\": \"agent-issues\"}}]";
// List<Object> objects = JSON.parseArray(channelProperties, ChannelPropertiesModel.class);
List<ChannelPropertiesModel> channelProperties2 = JSON.parseArray(channelProperties, ChannelPropertiesModel.class);
System.out.println(channelProperties2.size());
List<ChannelPropertiesModel> channelProperties1 = Lists.newArrayList();
ChannelPropertiesModel a = new ChannelPropertiesModel();
a.setAppId("5252");
ChannelModel mode = new ChannelModel();
mode.setAccessKey("123");
mode.setSecretKey("321");
a.setData(mode);
channelProperties1.add(a);
String jsonString = JSONObject.toJSONString(channelProperties1);
System.out.println(jsonString);
}
public String getChannelProperties() {
return channelProperties;
}

public void setChannelProperties(String channelProperties) {
this.channelProperties = channelProperties;
}
}

+ 24
- 0
src/main/java/com/taiji/system/oss/ChannelPropertiesModel.java 查看文件

@@ -0,0 +1,24 @@
package com.taiji.system.oss;

public class ChannelPropertiesModel {

private String appId;

private ChannelModel data;

public ChannelModel getData() {
return data;
}

public void setData(ChannelModel data) {
this.data = data;
}

public String getAppId() {
return appId;
}

public void setAppId(String appId) {
this.appId = appId;
}
}

+ 45
- 0
src/main/java/com/taiji/system/oss/FileUrlVo.java 查看文件

@@ -0,0 +1,45 @@
package com.taiji.system.oss;

import io.swagger.annotations.ApiModelProperty;
import org.springframework.web.multipart.MultipartFile;

/***
* <p>
*
* </p>
* @author hou yi
* @date 2022/11/22 16:52
**/
public class FileUrlVo {
@ApiModelProperty("文件地址")
private String fileUrl;

private MultipartFile file;

public FileUrlVo() {
}

public FileUrlVo(String fileUrl) {
this.fileUrl = fileUrl;
}

public FileUrlVo(MultipartFile file) {
this.file = file;
}

public String getFileUrl() {
return fileUrl;
}

public void setFileUrl(String fileUrl) {
this.fileUrl = fileUrl;
}

public MultipartFile getFile() {
return file;
}

public void setFile(MultipartFile file) {
this.file = file;
}
}

+ 728
- 0
src/main/java/com/taiji/system/oss/MinIoContentType.java 查看文件

@@ -0,0 +1,728 @@
package com.taiji.system.oss;

import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;

/***
* <p>
* MinIo contentType 工具类
* </p>
* @author hou yi
* @date 2022/11/21 15:29
**/
public class MinIoContentType {

/**
* 两种初始化Map常量
* 1.new HashMap
* 2.static 静态代码块
*/
static Map<String, String> contentType = new HashMap<String, String>(200) {
{
put(".jpg", "image/jpeg");
put(".jpeg", "image/jpeg");
}
};

/***
* 通过key获取ContentType值
* @param ext 文件后缀名
* @return 、
*/
public static String getContentType(String ext) {
String type = contentType.get(ext);
return StringUtils.hasLength(type) ? type : "application/octet-stream";
}

static {
contentType.put(".load", "text/html");
contentType.put(".123", "application/vnd.lotus-1-2-3");
contentType.put(".3ds", "image/x-3ds");
contentType.put(".3g2", "video/3gpp");
contentType.put(".3ga", "video/3gpp");
contentType.put(".3gp", "video/3gpp");
contentType.put(".3gpp", "video/3gpp");
contentType.put(".602", "application/x-t602");
contentType.put(".669", "audio/x-mod");
contentType.put(".7z", "application/x-7z-compressed");
contentType.put(".a", "application/x-archive");
contentType.put(".aac", "audio/mp4");
contentType.put(".abw", "application/x-abiword");
contentType.put(".abw.crashed", "application/x-abiword");
contentType.put(".abw.gz", "application/x-abiword");
contentType.put(".ac3", "audio/ac3");
contentType.put(".ace", "application/x-ace");
contentType.put(".adb", "text/x-adasrc");
contentType.put(".ads", "text/x-adasrc");
contentType.put(".afm", "application/x-font-afm");
contentType.put(".ag", "image/x-applix-graphics");
contentType.put(".ai", "application/illustrator");
contentType.put(".aif", "audio/x-aiff");
contentType.put(".aifc", "audio/x-aiff");
contentType.put(".aiff", "audio/x-aiff");
contentType.put(".al", "application/x-perl");
contentType.put(".alz", "application/x-alz");
contentType.put(".amr", "audio/amr");
contentType.put(".ani", "application/x-navi-animation");
contentType.put(".anim[1-9j]", "video/x-anim");
contentType.put(".anx", "application/annodex");
contentType.put(".ape", "audio/x-ape");
contentType.put(".arj", "application/x-arj");
contentType.put(".arw", "image/x-sony-arw");
contentType.put(".as", "application/x-applix-spreadsheet");
contentType.put(".asc", "text/plain");
contentType.put(".asf", "video/x-ms-asf");
contentType.put(".asp", "application/x-asp");
contentType.put(".ass", "text/x-ssa");
contentType.put(".asx", "audio/x-ms-asx");
contentType.put(".atom", "application/atom+xml");
contentType.put(".au", "audio/basic");
contentType.put(".avi", "video/x-msvideo");
contentType.put(".aw", "application/x-applix-word");
contentType.put(".awb", "audio/amr-wb");
contentType.put(".awk", "application/x-awk");
contentType.put(".axa", "audio/annodex");
contentType.put(".axv", "video/annodex");
contentType.put(".bak", "application/x-trash");
contentType.put(".bcpio", "application/x-bcpio");
contentType.put(".bdf", "application/x-font-bdf");
contentType.put(".bib", "text/x-bibtex");
contentType.put(".bin", "application/octet-stream");
contentType.put(".blend", "application/x-blender");
contentType.put(".blender", "application/x-blender");
contentType.put(".bmp", "image/bmp");
contentType.put(".bz", "application/x-bzip");
contentType.put(".bz2", "application/x-bzip");
contentType.put(".c", "text/x-csrc");
contentType.put(".c++", "text/x-c++src");
contentType.put(".cab", "application/vnd.ms-cab-compressed");
contentType.put(".cb7", "application/x-cb7");
contentType.put(".cbr", "application/x-cbr");
contentType.put(".cbt", "application/x-cbt");
contentType.put(".cbz", "application/x-cbz");
contentType.put(".cc", "text/x-c++src");
contentType.put(".cdf", "application/x-netcdf");
contentType.put(".cdr", "application/vnd.corel-draw");
contentType.put(".cer", "application/x-x509-ca-cert");
contentType.put(".cert", "application/x-x509-ca-cert");
contentType.put(".cgm", "image/cgm");
contentType.put(".chm", "application/x-chm");
contentType.put(".chrt", "application/x-kchart");
contentType.put(".class", "application/x-java");
contentType.put(".cls", "text/x-tex");
contentType.put(".cmake", "text/x-cmake");
contentType.put(".cpio", "application/x-cpio");
contentType.put(".cpio.gz", "application/x-cpio-compressed");
contentType.put(".cpp", "text/x-c++src");
contentType.put(".cr2", "image/x-canon-cr2");
contentType.put(".crt", "application/x-x509-ca-cert");
contentType.put(".crw", "image/x-canon-crw");
contentType.put(".cs", "text/x-csharp");
contentType.put(".csh", "application/x-csh");
contentType.put(".css", "text/css");
contentType.put(".cssl", "text/css");
contentType.put(".csv", "text/csv");
contentType.put(".cue", "application/x-cue");
contentType.put(".cur", "image/x-win-bitmap");
contentType.put(".cxx", "text/x-c++src");
contentType.put(".d", "text/x-dsrc");
contentType.put(".dar", "application/x-dar");
contentType.put(".dbf", "application/x-dbf");
contentType.put(".dc", "application/x-dc-rom");
contentType.put(".dcl", "text/x-dcl");
contentType.put(".dcm", "application/dicom");
contentType.put(".dcr", "image/x-kodak-dcr");
contentType.put(".dds", "image/x-dds");
contentType.put(".deb", "application/x-deb");
contentType.put(".der", "application/x-x509-ca-cert");
contentType.put(".desktop", "application/x-desktop");
contentType.put(".dia", "application/x-dia-diagram");
contentType.put(".diff", "text/x-patch");
contentType.put(".divx", "video/x-msvideo");
contentType.put(".djv", "image/vnd.djvu");
contentType.put(".djvu", "image/vnd.djvu");
contentType.put(".dng", "image/x-adobe-dng");
contentType.put(".doc", "application/msword");
contentType.put(".docbook", "application/docbook+xml");
contentType.put(".docm", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
contentType.put(".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
contentType.put(".dot", "text/vnd.graphviz");
contentType.put(".dsl", "text/x-dsl");
contentType.put(".dtd", "application/xml-dtd");
contentType.put(".dtx", "text/x-tex");
contentType.put(".dv", "video/dv");
contentType.put(".dvi", "application/x-dvi");
contentType.put(".dvi.bz2", "application/x-bzdvi");
contentType.put(".dvi.gz", "application/x-gzdvi");
contentType.put(".dwg", "image/vnd.dwg");
contentType.put(".dxf", "image/vnd.dxf");
contentType.put(".e", "text/x-eiffel");
contentType.put(".egon", "application/x-egon");
contentType.put(".eif", "text/x-eiffel");
contentType.put(".el", "text/x-emacs-lisp");
contentType.put(".emf", "image/x-emf");
contentType.put(".emp", "application/vnd.emusic-emusic_package");
contentType.put(".ent", "application/xml-external-parsed-entity");
contentType.put(".eps", "image/x-eps");
contentType.put(".eps.bz2", "image/x-bzeps");
contentType.put(".eps.gz", "image/x-gzeps");
contentType.put(".epsf", "image/x-eps");
contentType.put(".epsf.bz2", "image/x-bzeps");
contentType.put(".epsf.gz", "image/x-gzeps");
contentType.put(".epsi", "image/x-eps");
contentType.put(".epsi.bz2", "image/x-bzeps");
contentType.put(".epsi.gz", "image/x-gzeps");
contentType.put(".epub", "application/epub+zip");
contentType.put(".erl", "text/x-erlang");
contentType.put(".es", "application/ecmascript");
contentType.put(".etheme", "application/x-e-theme");
contentType.put(".etx", "text/x-setext");
contentType.put(".exe", "application/x-ms-dos-executable");
contentType.put(".exr", "image/x-exr");
contentType.put(".ez", "application/andrew-inset");
contentType.put(".f", "text/x-fortran");
contentType.put(".f90", "text/x-fortran");
contentType.put(".f95", "text/x-fortran");
contentType.put(".fb2", "application/x-fictionbook+xml");
contentType.put(".fig", "image/x-xfig");
contentType.put(".fits", "image/fits");
contentType.put(".fl", "application/x-fluid");
contentType.put(".flac", "audio/x-flac");
contentType.put(".flc", "video/x-flic");
contentType.put(".fli", "video/x-flic");
contentType.put(".flv", "video/x-flv");
contentType.put(".flw", "application/x-kivio");
contentType.put(".fo", "text/x-xslfo");
contentType.put(".for", "text/x-fortran");
contentType.put(".g3", "image/fax-g3");
contentType.put(".gb", "application/x-gameboy-rom");
contentType.put(".gba", "application/x-gba-rom");
contentType.put(".gcrd", "text/directory");
contentType.put(".ged", "application/x-gedcom");
contentType.put(".gedcom", "application/x-gedcom");
contentType.put(".gen", "application/x-genesis-rom");
contentType.put(".gf", "application/x-tex-gf");
contentType.put(".gg", "application/x-sms-rom");
contentType.put(".gif", "image/gif");
contentType.put(".glade", "application/x-glade");
contentType.put(".gmo", "application/x-gettext-translation");
contentType.put(".gnc", "application/x-gnucash");
contentType.put(".gnd", "application/gnunet-directory");
contentType.put(".gnucash", "application/x-gnucash");
contentType.put(".gnumeric", "application/x-gnumeric");
contentType.put(".gnuplot", "application/x-gnuplot");
contentType.put(".gp", "application/x-gnuplot");
contentType.put(".gpg", "application/pgp-encrypted");
contentType.put(".gplt", "application/x-gnuplot");
contentType.put(".gra", "application/x-graphite");
contentType.put(".gsf", "application/x-font-type1");
contentType.put(".gsm", "audio/x-gsm");
contentType.put(".gtar", "application/x-tar");
contentType.put(".gv", "text/vnd.graphviz");
contentType.put(".gvp", "text/x-google-video-pointer");
contentType.put(".gz", "application/x-gzip");
contentType.put(".h", "text/x-chdr");
contentType.put(".h++", "text/x-c++hdr");
contentType.put(".hdf", "application/x-hdf");
contentType.put(".hh", "text/x-c++hdr");
contentType.put(".hp", "text/x-c++hdr");
contentType.put(".hpgl", "application/vnd.hp-hpgl");
contentType.put(".hpp", "text/x-c++hdr");
contentType.put(".hs", "text/x-haskell");
contentType.put(".htm", "text/html");
contentType.put(".html", "text/html");
contentType.put(".hwp", "application/x-hwp");
contentType.put(".hwt", "application/x-hwt");
contentType.put(".hxx", "text/x-c++hdr");
contentType.put(".ica", "application/x-ica");
contentType.put(".icb", "image/x-tga");
contentType.put(".icns", "image/x-icns");
contentType.put(".ico", "image/vnd.microsoft.icon");
contentType.put(".ics", "text/calendar");
contentType.put(".idl", "text/x-idl");
contentType.put(".ief", "image/ief");
contentType.put(".iff", "image/x-iff");
contentType.put(".ilbm", "image/x-ilbm");
contentType.put(".ime", "text/x-imelody");
contentType.put(".imy", "text/x-imelody");
contentType.put(".ins", "text/x-tex");
contentType.put(".iptables", "text/x-iptables");
contentType.put(".iso", "application/x-cd-image");
contentType.put(".iso9660", "application/x-cd-image");
contentType.put(".it", "audio/x-it");
contentType.put(".j2k", "image/jp2");
contentType.put(".jad", "text/vnd.sun.j2me.app-descriptor");
contentType.put(".jar", "application/x-java-archive");
contentType.put(".java", "text/x-java");
contentType.put(".jng", "image/x-jng");
contentType.put(".jnlp", "application/x-java-jnlp-file");
contentType.put(".jp2", "image/jp2");
contentType.put(".jpc", "image/jp2");
contentType.put(".jfif", "image/jpeg");
contentType.put(".jpe", "image/jpeg");
contentType.put(".jpeg", "image/jpeg");
contentType.put(".jpf", "image/jp2");
contentType.put(".jpg", "image/jpeg");
contentType.put(".jpr", "application/x-jbuilder-project");
contentType.put(".jpx", "image/jp2");
contentType.put(".js", "application/javascript");
contentType.put(".json", "application/json");
contentType.put(".jsonp", "application/jsonp");
contentType.put(".k25", "image/x-kodak-k25");
contentType.put(".kar", "audio/midi");
contentType.put(".karbon", "application/x-karbon");
contentType.put(".kdc", "image/x-kodak-kdc");
contentType.put(".kdelnk", "application/x-desktop");
contentType.put(".kexi", "application/x-kexiproject-sqlite3");
contentType.put(".kexic", "application/x-kexi-connectiondata");
contentType.put(".kexis", "application/x-kexiproject-shortcut");
contentType.put(".kfo", "application/x-kformula");
contentType.put(".kil", "application/x-killustrator");
contentType.put(".kino", "application/smil");
contentType.put(".kml", "application/vnd.google-earth.kml+xml");
contentType.put(".kmz", "application/vnd.google-earth.kmz");
contentType.put(".kon", "application/x-kontour");
contentType.put(".kpm", "application/x-kpovmodeler");
contentType.put(".kpr", "application/x-kpresenter");
contentType.put(".kpt", "application/x-kpresenter");
contentType.put(".kra", "application/x-krita");
contentType.put(".ksp", "application/x-kspread");
contentType.put(".kud", "application/x-kugar");
contentType.put(".kwd", "application/x-kword");
contentType.put(".kwt", "application/x-kword");
contentType.put(".la", "application/x-shared-library-la");
contentType.put(".latex", "text/x-tex");
contentType.put(".ldif", "text/x-ldif");
contentType.put(".lha", "application/x-lha");
contentType.put(".lhs", "text/x-literate-haskell");
contentType.put(".lhz", "application/x-lhz");
contentType.put(".log", "text/x-log");
contentType.put(".ltx", "text/x-tex");
contentType.put(".lua", "text/x-lua");
contentType.put(".lwo", "image/x-lwo");
contentType.put(".lwob", "image/x-lwo");
contentType.put(".lws", "image/x-lws");
contentType.put(".ly", "text/x-lilypond");
contentType.put(".lyx", "application/x-lyx");
contentType.put(".lz", "application/x-lzip");
contentType.put(".lzh", "application/x-lha");
contentType.put(".lzma", "application/x-lzma");
contentType.put(".lzo", "application/x-lzop");
contentType.put(".m", "text/x-matlab");
contentType.put(".m15", "audio/x-mod");
contentType.put(".m2t", "video/mpeg");
contentType.put(".m3u", "audio/x-mpegurl");
contentType.put(".m3u8", "audio/x-mpegurl");
contentType.put(".m4", "application/x-m4");
contentType.put(".m4a", "audio/mp4");
contentType.put(".m4b", "audio/x-m4b");
contentType.put(".m4v", "video/mp4");
contentType.put(".mab", "application/x-markaby");
contentType.put(".man", "application/x-troff-man");
contentType.put(".mbox", "application/mbox");
contentType.put(".md", "application/x-genesis-rom");
contentType.put(".mdb", "application/vnd.ms-access");
contentType.put(".mdi", "image/vnd.ms-modi");
contentType.put(".me", "text/x-troff-me");
contentType.put(".med", "audio/x-mod");
contentType.put(".metalink", "application/metalink+xml");
contentType.put(".mgp", "application/x-magicpoint");
contentType.put(".mid", "audio/midi");
contentType.put(".midi", "audio/midi");
contentType.put(".mif", "application/x-mif");
contentType.put(".minipsf", "audio/x-minipsf");
contentType.put(".mka", "audio/x-matroska");
contentType.put(".mkv", "video/x-matroska");
contentType.put(".ml", "text/x-ocaml");
contentType.put(".mli", "text/x-ocaml");
contentType.put(".mm", "text/x-troff-mm");
contentType.put(".mmf", "application/x-smaf");
contentType.put(".mml", "text/mathml");
contentType.put(".mng", "video/x-mng");
contentType.put(".mo", "application/x-gettext-translation");
contentType.put(".mo3", "audio/x-mo3");
contentType.put(".moc", "text/x-moc");
contentType.put(".mod", "audio/x-mod");
contentType.put(".mof", "text/x-mof");
contentType.put(".moov", "video/quicktime");
contentType.put(".mov", "video/quicktime");
contentType.put(".movie", "video/x-sgi-movie");
contentType.put(".mp+", "audio/x-musepack");
contentType.put(".mp2", "video/mpeg");
contentType.put(".mp3", "audio/mpeg");
contentType.put(".mp4", "video/mp4");
contentType.put(".mpc", "audio/x-musepack");
contentType.put(".mpe", "video/mpeg");
contentType.put(".mpeg", "video/mpeg");
contentType.put(".mpg", "video/mpeg");
contentType.put(".mpga", "audio/mpeg");
contentType.put(".mpp", "audio/x-musepack");
contentType.put(".mrl", "text/x-mrml");
contentType.put(".mrml", "text/x-mrml");
contentType.put(".mrw", "image/x-minolta-mrw");
contentType.put(".ms", "text/x-troff-ms");
contentType.put(".msi", "application/x-msi");
contentType.put(".msod", "image/x-msod");
contentType.put(".msx", "application/x-msx-rom");
contentType.put(".mtm", "audio/x-mod");
contentType.put(".mup", "text/x-mup");
contentType.put(".mxf", "application/mxf");
contentType.put(".n64", "application/x-n64-rom");
contentType.put(".nb", "application/mathematica");
contentType.put(".nc", "application/x-netcdf");
contentType.put(".nds", "application/x-nintendo-ds-rom");
contentType.put(".nef", "image/x-nikon-nef");
contentType.put(".nes", "application/x-nes-rom");
contentType.put(".nfo", "text/x-nfo");
contentType.put(".not", "text/x-mup");
contentType.put(".nsc", "application/x-netshow-channel");
contentType.put(".nsv", "video/x-nsv");
contentType.put(".o", "application/x-object");
contentType.put(".obj", "application/x-tgif");
contentType.put(".ocl", "text/x-ocl");
contentType.put(".oda", "application/oda");
contentType.put(".odb", "application/vnd.oasis.opendocument.database");
contentType.put(".odc", "application/vnd.oasis.opendocument.chart");
contentType.put(".odf", "application/vnd.oasis.opendocument.formula");
contentType.put(".odg", "application/vnd.oasis.opendocument.graphics");
contentType.put(".odi", "application/vnd.oasis.opendocument.image");
contentType.put(".odm", "application/vnd.oasis.opendocument.text-master");
contentType.put(".odp", "application/vnd.oasis.opendocument.presentation");
contentType.put(".ods", "application/vnd.oasis.opendocument.spreadsheet");
contentType.put(".odt", "application/vnd.oasis.opendocument.text");
contentType.put(".oga", "audio/ogg");
contentType.put(".ogg", "video/x-theora+ogg");
contentType.put(".ogm", "video/x-ogm+ogg");
contentType.put(".ogv", "video/ogg");
contentType.put(".ogx", "application/ogg");
contentType.put(".old", "application/x-trash");
contentType.put(".oleo", "application/x-oleo");
contentType.put(".opml", "text/x-opml+xml");
contentType.put(".ora", "image/openraster");
contentType.put(".orf", "image/x-olympus-orf");
contentType.put(".otc", "application/vnd.oasis.opendocument.chart-template");
contentType.put(".otf", "application/x-font-otf");
contentType.put(".otg", "application/vnd.oasis.opendocument.graphics-template");
contentType.put(".oth", "application/vnd.oasis.opendocument.text-web");
contentType.put(".otp", "application/vnd.oasis.opendocument.presentation-template");
contentType.put(".ots", "application/vnd.oasis.opendocument.spreadsheet-template");
contentType.put(".ott", "application/vnd.oasis.opendocument.text-template");
contentType.put(".owl", "application/rdf+xml");
contentType.put(".oxt", "application/vnd.openofficeorg.extension");
contentType.put(".p", "text/x-pascal");
contentType.put(".p10", "application/pkcs10");
contentType.put(".p12", "application/x-pkcs12");
contentType.put(".p7b", "application/x-pkcs7-certificates");
contentType.put(".p7s", "application/pkcs7-signature");
contentType.put(".pack", "application/x-java-pack200");
contentType.put(".pak", "application/x-pak");
contentType.put(".par2", "application/x-par2");
contentType.put(".pas", "text/x-pascal");
contentType.put(".patch", "text/x-patch");
contentType.put(".pbm", "image/x-portable-bitmap");
contentType.put(".pcd", "image/x-photo-cd");
contentType.put(".pcf", "application/x-cisco-vpn-settings");
contentType.put(".pcf.gz", "application/x-font-pcf");
contentType.put(".pcf.z", "application/x-font-pcf");
contentType.put(".pcl", "application/vnd.hp-pcl");
contentType.put(".pcx", "image/x-pcx");
contentType.put(".pdb", "chemical/x-pdb");
contentType.put(".pdc", "application/x-aportisdoc");
contentType.put(".pdf", "application/pdf");
contentType.put(".pdf.bz2", "application/x-bzpdf");
contentType.put(".pdf.gz", "application/x-gzpdf");
contentType.put(".pef", "image/x-pentax-pef");
contentType.put(".pem", "application/x-x509-ca-cert");
contentType.put(".perl", "application/x-perl");
contentType.put(".pfa", "application/x-font-type1");
contentType.put(".pfb", "application/x-font-type1");
contentType.put(".pfx", "application/x-pkcs12");
contentType.put(".pgm", "image/x-portable-graymap");
contentType.put(".pgn", "application/x-chess-pgn");
contentType.put(".pgp", "application/pgp-encrypted");
contentType.put(".php", "application/x-php");
contentType.put(".php3", "application/x-php");
contentType.put(".php4", "application/x-php");
contentType.put(".pict", "image/x-pict");
contentType.put(".pict1", "image/x-pict");
contentType.put(".pict2", "image/x-pict");
contentType.put(".pickle", "application/python-pickle");
contentType.put(".pk", "application/x-tex-pk");
contentType.put(".pkipath", "application/pkix-pkipath");
contentType.put(".pkr", "application/pgp-keys");
contentType.put(".pl", "application/x-perl");
contentType.put(".pla", "audio/x-iriver-pla");
contentType.put(".pln", "application/x-planperfect");
contentType.put(".pls", "audio/x-scpls");
contentType.put(".pm", "application/x-perl");
contentType.put(".png", "image/png");
contentType.put(".pnm", "image/x-portable-anymap");
contentType.put(".pntg", "image/x-macpaint");
contentType.put(".po", "text/x-gettext-translation");
contentType.put(".por", "application/x-spss-por");
contentType.put(".pot", "text/x-gettext-translation-template");
contentType.put(".ppm", "image/x-portable-pixmap");
contentType.put(".pps", "application/vnd.ms-powerpoint");
contentType.put(".ppt", "application/vnd.ms-powerpoint");
contentType.put(".pptm", "application/vnd.openxmlformats-officedocument.presentationml.presentation");
contentType.put(".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation");
contentType.put(".ppz", "application/vnd.ms-powerpoint");
contentType.put(".prc", "application/x-palm-database");
contentType.put(".ps", "application/postscript");
contentType.put(".ps.bz2", "application/x-bzpostscript");
contentType.put(".ps.gz", "application/x-gzpostscript");
contentType.put(".psd", "image/vnd.adobe.photoshop");
contentType.put(".psf", "audio/x-psf");
contentType.put(".psf.gz", "application/x-gz-font-linux-psf");
contentType.put(".psflib", "audio/x-psflib");
contentType.put(".psid", "audio/prs.sid");
contentType.put(".psw", "application/x-pocket-word");
contentType.put(".pw", "application/x-pw");
contentType.put(".py", "text/x-python");
contentType.put(".pyc", "application/x-python-bytecode");
contentType.put(".pyo", "application/x-python-bytecode");
contentType.put(".qif", "image/x-quicktime");
contentType.put(".qt", "video/quicktime");
contentType.put(".qtif", "image/x-quicktime");
contentType.put(".qtl", "application/x-quicktime-media-link");
contentType.put(".qtvr", "video/quicktime");
contentType.put(".ra", "audio/vnd.rn-realaudio");
contentType.put(".raf", "image/x-fuji-raf");
contentType.put(".ram", "application/ram");
contentType.put(".rar", "application/x-rar");
contentType.put(".ras", "image/x-cmu-raster");
contentType.put(".raw", "image/x-panasonic-raw");
contentType.put(".rax", "audio/vnd.rn-realaudio");
contentType.put(".rb", "application/x-ruby");
contentType.put(".rdf", "application/rdf+xml");
contentType.put(".rdfs", "application/rdf+xml");
contentType.put(".reg", "text/x-ms-regedit");
contentType.put(".rej", "application/x-reject");
contentType.put(".rgb", "image/x-rgb");
contentType.put(".rle", "image/rle");
contentType.put(".rm", "application/vnd.rn-realmedia");
contentType.put(".rmj", "application/vnd.rn-realmedia");
contentType.put(".rmm", "application/vnd.rn-realmedia");
contentType.put(".rms", "application/vnd.rn-realmedia");
contentType.put(".rmvb", "application/vnd.rn-realmedia");
contentType.put(".rmx", "application/vnd.rn-realmedia");
contentType.put(".roff", "text/troff");
contentType.put(".rp", "image/vnd.rn-realpix");
contentType.put(".rpm", "application/x-rpm");
contentType.put(".rss", "application/rss+xml");
contentType.put(".rt", "text/vnd.rn-realtext");
contentType.put(".rtf", "application/rtf");
contentType.put(".rtx", "text/richtext");
contentType.put(".rv", "video/vnd.rn-realvideo");
contentType.put(".rvx", "video/vnd.rn-realvideo");
contentType.put(".s3m", "audio/x-s3m");
contentType.put(".sam", "application/x-amipro");
contentType.put(".sami", "application/x-sami");
contentType.put(".sav", "application/x-spss-sav");
contentType.put(".scm", "text/x-scheme");
contentType.put(".sda", "application/vnd.stardivision.draw");
contentType.put(".sdc", "application/vnd.stardivision.calc");
contentType.put(".sdd", "application/vnd.stardivision.impress");
contentType.put(".sdp", "application/sdp");
contentType.put(".sds", "application/vnd.stardivision.chart");
contentType.put(".sdw", "application/vnd.stardivision.writer");
contentType.put(".sgf", "application/x-go-sgf");
contentType.put(".sgi", "image/x-sgi");
contentType.put(".sgl", "application/vnd.stardivision.writer");
contentType.put(".sgm", "text/sgml");
contentType.put(".sgml", "text/sgml");
contentType.put(".sh", "application/x-shellscript");
contentType.put(".shar", "application/x-shar");
contentType.put(".shn", "application/x-shorten");
contentType.put(".siag", "application/x-siag");
contentType.put(".sid", "audio/prs.sid");
contentType.put(".sik", "application/x-trash");
contentType.put(".sis", "application/vnd.symbian.install");
contentType.put(".sisx", "x-epoc/x-sisx-app");
contentType.put(".sit", "application/x-stuffit");
contentType.put(".siv", "application/sieve");
contentType.put(".sk", "image/x-skencil");
contentType.put(".sk1", "image/x-skencil");
contentType.put(".skr", "application/pgp-keys");
contentType.put(".slk", "text/spreadsheet");
contentType.put(".smaf", "application/x-smaf");
contentType.put(".smc", "application/x-snes-rom");
contentType.put(".smd", "application/vnd.stardivision.mail");
contentType.put(".smf", "application/vnd.stardivision.math");
contentType.put(".smi", "application/x-sami");
contentType.put(".smil", "application/smil");
contentType.put(".sml", "application/smil");
contentType.put(".sms", "application/x-sms-rom");
contentType.put(".snd", "audio/basic");
contentType.put(".so", "application/x-sharedlib");
contentType.put(".spc", "application/x-pkcs7-certificates");
contentType.put(".spd", "application/x-font-speedo");
contentType.put(".spec", "text/x-rpm-spec");
contentType.put(".spl", "application/x-shockwave-flash");
contentType.put(".spx", "audio/x-speex");
contentType.put(".sql", "text/x-sql");
contentType.put(".sr2", "image/x-sony-sr2");
contentType.put(".src", "application/x-wais-source");
contentType.put(".srf", "image/x-sony-srf");
contentType.put(".srt", "application/x-subrip");
contentType.put(".ssa", "text/x-ssa");
contentType.put(".stc", "application/vnd.sun.xml.calc.template");
contentType.put(".std", "application/vnd.sun.xml.draw.template");
contentType.put(".sti", "application/vnd.sun.xml.impress.template");
contentType.put(".stm", "audio/x-stm");
contentType.put(".stw", "application/vnd.sun.xml.writer.template");
contentType.put(".sty", "text/x-tex");
contentType.put(".sub", "text/x-subviewer");
contentType.put(".sun", "image/x-sun-raster");
contentType.put(".sv4cpio", "application/x-sv4cpio");
contentType.put(".sv4crc", "application/x-sv4crc");
contentType.put(".svg", "image/svg+xml");
contentType.put(".svgz", "image/svg+xml-compressed");
contentType.put(".swf", "application/x-shockwave-flash");
contentType.put(".sxc", "application/vnd.sun.xml.calc");
contentType.put(".sxd", "application/vnd.sun.xml.draw");
contentType.put(".sxg", "application/vnd.sun.xml.writer.global");
contentType.put(".sxi", "application/vnd.sun.xml.impress");
contentType.put(".sxm", "application/vnd.sun.xml.math");
contentType.put(".sxw", "application/vnd.sun.xml.writer");
contentType.put(".sylk", "text/spreadsheet");
contentType.put(".t", "text/troff");
contentType.put(".t2t", "text/x-txt2tags");
contentType.put(".tar", "application/x-tar");
contentType.put(".tar.bz", "application/x-bzip-compressed-tar");
contentType.put(".tar.bz2", "application/x-bzip-compressed-tar");
contentType.put(".tar.gz", "application/x-compressed-tar");
contentType.put(".tar.lzma", "application/x-lzma-compressed-tar");
contentType.put(".tar.lzo", "application/x-tzo");
contentType.put(".tar.xz", "application/x-xz-compressed-tar");
contentType.put(".tar.z", "application/x-tarz");
contentType.put(".tbz", "application/x-bzip-compressed-tar");
contentType.put(".tbz2", "application/x-bzip-compressed-tar");
contentType.put(".tcl", "text/x-tcl");
contentType.put(".tex", "text/x-tex");
contentType.put(".texi", "text/x-texinfo");
contentType.put(".texinfo", "text/x-texinfo");
contentType.put(".tga", "image/x-tga");
contentType.put(".tgz", "application/x-compressed-tar");
contentType.put(".theme", "application/x-theme");
contentType.put(".themepack", "application/x-windows-themepack");
contentType.put(".tif", "image/tiff");
contentType.put(".tiff", "image/tiff");
contentType.put(".tk", "text/x-tcl");
contentType.put(".tlz", "application/x-lzma-compressed-tar");
contentType.put(".tnef", "application/vnd.ms-tnef");
contentType.put(".tnf", "application/vnd.ms-tnef");
contentType.put(".toc", "application/x-cdrdao-toc");
contentType.put(".torrent", "application/x-bittorrent");
contentType.put(".tpic", "image/x-tga");
contentType.put(".tr", "text/troff");
contentType.put(".ts", "application/x-linguist");
contentType.put(".tsv", "text/tab-separated-values");
contentType.put(".tta", "audio/x-tta");
contentType.put(".ttc", "application/x-font-ttf");
contentType.put(".ttf", "application/x-font-ttf");
contentType.put(".ttx", "application/x-font-ttx");
contentType.put(".txt", "text/plain");
contentType.put(".txz", "application/x-xz-compressed-tar");
contentType.put(".tzo", "application/x-tzo");
contentType.put(".ufraw", "application/x-ufraw");
contentType.put(".ui", "application/x-designer");
contentType.put(".uil", "text/x-uil");
contentType.put(".ult", "audio/x-mod");
contentType.put(".uni", "audio/x-mod");
contentType.put(".uri", "text/x-uri");
contentType.put(".url", "text/x-uri");
contentType.put(".ustar", "application/x-ustar");
contentType.put(".vala", "text/x-vala");
contentType.put(".vapi", "text/x-vala");
contentType.put(".vcf", "text/directory");
contentType.put(".vcs", "text/calendar");
contentType.put(".vct", "text/directory");
contentType.put(".vda", "image/x-tga");
contentType.put(".vhd", "text/x-vhdl");
contentType.put(".vhdl", "text/x-vhdl");
contentType.put(".viv", "video/vivo");
contentType.put(".vivo", "video/vivo");
contentType.put(".vlc", "audio/x-mpegurl");
contentType.put(".vob", "video/mpeg");
contentType.put(".voc", "audio/x-voc");
contentType.put(".vor", "application/vnd.stardivision.writer");
contentType.put(".vst", "image/x-tga");
contentType.put(".wav", "audio/x-wav");
contentType.put(".wax", "audio/x-ms-asx");
contentType.put(".wb1", "application/x-quattropro");
contentType.put(".wb2", "application/x-quattropro");
contentType.put(".wb3", "application/x-quattropro");
contentType.put(".wbmp", "image/vnd.wap.wbmp");
contentType.put(".wcm", "application/vnd.ms-works");
contentType.put(".wdb", "application/vnd.ms-works");
contentType.put(".webm", "video/webm");
contentType.put(".wk1", "application/vnd.lotus-1-2-3");
contentType.put(".wk3", "application/vnd.lotus-1-2-3");
contentType.put(".wk4", "application/vnd.lotus-1-2-3");
contentType.put(".wks", "application/vnd.ms-works");
contentType.put(".wma", "audio/x-ms-wma");
contentType.put(".wmf", "image/x-wmf");
contentType.put(".wml", "text/vnd.wap.wml");
contentType.put(".wmls", "text/vnd.wap.wmlscript");
contentType.put(".wmv", "video/x-ms-wmv");
contentType.put(".wmx", "audio/x-ms-asx");
contentType.put(".wp", "application/vnd.wordperfect");
contentType.put(".wp4", "application/vnd.wordperfect");
contentType.put(".wp5", "application/vnd.wordperfect");
contentType.put(".wp6", "application/vnd.wordperfect");
contentType.put(".wpd", "application/vnd.wordperfect");
contentType.put(".wpg", "application/x-wpg");
contentType.put(".wpl", "application/vnd.ms-wpl");
contentType.put(".wpp", "application/vnd.wordperfect");
contentType.put(".wps", "application/vnd.ms-works");
contentType.put(".wri", "application/x-mswrite");
contentType.put(".wrl", "model/vrml");
contentType.put(".wv", "audio/x-wavpack");
contentType.put(".wvc", "audio/x-wavpack-correction");
contentType.put(".wvp", "audio/x-wavpack");
contentType.put(".wvx", "audio/x-ms-asx");
contentType.put(".x3f", "image/x-sigma-x3f");
contentType.put(".xac", "application/x-gnucash");
contentType.put(".xbel", "application/x-xbel");
contentType.put(".xbl", "application/xml");
contentType.put(".xbm", "image/x-xbitmap");
contentType.put(".xcf", "image/x-xcf");
contentType.put(".xcf.bz2", "image/x-compressed-xcf");
contentType.put(".xcf.gz", "image/x-compressed-xcf");
contentType.put(".xhtml", "application/xhtml+xml");
contentType.put(".xi", "audio/x-xi");
contentType.put(".xla", "application/vnd.ms-excel");
contentType.put(".xlc", "application/vnd.ms-excel");
contentType.put(".xld", "application/vnd.ms-excel");
contentType.put(".xlf", "application/x-xliff");
contentType.put(".xliff", "application/x-xliff");
contentType.put(".xll", "application/vnd.ms-excel");
contentType.put(".xlm", "application/vnd.ms-excel");
contentType.put(".xls", "application/vnd.ms-excel");
contentType.put(".xlsm", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
contentType.put(".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
contentType.put(".xlt", "application/vnd.ms-excel");
contentType.put(".xlw", "application/vnd.ms-excel");
contentType.put(".xm", "audio/x-xm");
contentType.put(".xmf", "audio/x-xmf");
contentType.put(".xmi", "text/x-xmi");
contentType.put(".xml", "application/xml");
contentType.put(".xpm", "image/x-xpixmap");
contentType.put(".xps", "application/vnd.ms-xpsdocument");
contentType.put(".xsl", "application/xml");
contentType.put(".xslfo", "text/x-xslfo");
contentType.put(".xslt", "application/xml");
contentType.put(".xspf", "application/xspf+xml");
contentType.put(".xul", "application/vnd.mozilla.xul+xml");
contentType.put(".xwd", "image/x-xwindowdump");
contentType.put(".xyz", "chemical/x-pdb");
contentType.put(".xz", "application/x-xz");
contentType.put(".w2p", "application/w2p");
contentType.put(".z", "application/x-compress");
contentType.put(".zabw", "application/x-abiword");
contentType.put(".zip", "application/zip");
}
}

+ 358
- 0
src/main/java/com/taiji/system/oss/MinIoTemplate.java 查看文件

@@ -0,0 +1,358 @@
package com.taiji.system.oss;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.taiji.system.util.GlobalException;
import io.minio.*;
import io.minio.http.Method;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/***
* <p>
* minio 模板
* </p>
* @author hou yi
* @date 2022/11/21 11:01
**/
public class MinIoTemplate {

private static final Logger log = LoggerFactory.getLogger(MinIoTemplate.class);

/*** MinIo 客户端*/
private final MinioClient minioClient;

/*** OSS 配置类*/
private final OssProperties ossProperties;

private final ChannelProperties channelProperties;

public MinIoTemplate(MinioClient minioClient, OssProperties ossProperties, ChannelProperties channelProperties) {
this.minioClient = minioClient;
this.ossProperties = ossProperties;
this.channelProperties = channelProperties;
}

/***
* 存储桶是否存在
* @param bucketName 存储桶名称
* @return 、
*/
public boolean bucketExists(String bucketName) {
try {
return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
} catch (Exception e) {
e.printStackTrace();
log.error("MinIo 判断存储桶是否存在失败...{}", e.getMessage());
throw new GlobalException("MinIo 判断存储桶是否存在失败...");
}
}

/**
* 创建存储桶
*
* @param bucketName 桶名
*/
public void makeBucket(String bucketName) {
if (!bucketExists(bucketName)) {
try {
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
} catch (Exception e) {
log.error("MinIo 创建存储桶失败...{}", e.getMessage());
throw new GlobalException("MinIo 创建存储桶失败...");
}
}
}

/**
* 上传文件
*
* @param file 流
* @param originalFileName 原始文件名
* @param bucketName 桶名
* @param deduplication true 同文件夹下生产唯一的文件名, false 同文件夹下相同文件名时直接覆盖
* @return OssFile
*/
public OssFile putObject(MultipartFile file, String bucketName, String originalFileName, boolean deduplication, String busCode) {
String uuidFileName = deduplication ? generateOssUuidFileName(originalFileName, busCode) : generateOssFileName(originalFileName, busCode);
try {
if (!StringUtils.hasLength(bucketName)) {
bucketName = ossProperties.getDefaultBucketName();
}
InputStream inputStream = file.getInputStream();
minioClient.putObject(PutObjectArgs.builder()
.bucket(bucketName)
.object(uuidFileName)
.stream(inputStream, inputStream.available(), -1)
.contentType(MinIoContentType.getContentType(originalFileName.substring(originalFileName.lastIndexOf("."))))
.build());
return new OssFile(uuidFileName, originalFileName);
} catch (Exception e) {
log.error("MinIo 上传文件失败...{}", e.getMessage());
throw new GlobalException("MinIo 上传文件失败...请联系管理员");
}
}

/**
* 上传文件
*
* @param file 流
* @param originalFileName 原始文件名
* @param deduplication true 同文件夹下生产唯一的文件名, false 同文件夹下相同文件名时直接覆盖
* @return OssFile
*/
public OssFile putObject(MultipartFile file, String appId, String key, String originalFileName, boolean deduplication) {
List<ChannelPropertiesModel> jsonObject = JSONObject.parseArray(channelProperties.getChannelProperties(), ChannelPropertiesModel.class);
ChannelPropertiesModel imodel = null;
for (ChannelPropertiesModel model :
jsonObject) {
if (model.getAppId().equals(appId)) {
imodel = model;
}
}
if (imodel == null) {
throw new GlobalException("当前appId未授权");
}
if (!imodel.getData().getAccessKey().equals(key)) {
throw new GlobalException("key值校验失败,请输入正确的key");
}
ChannelModel data = imodel.getData();
MinioClient minioClient = minioBuild(data);
String uuidFileName = deduplication ? generateOssUuidFileName(originalFileName, "") : generateOssFileName(originalFileName,"");
try {
InputStream inputStream = file.getInputStream();
minioClient.putObject(PutObjectArgs.builder()
.bucket("agent-issues")
.object(appId + "/" + uuidFileName)
.stream(inputStream, inputStream.available(), -1)
.contentType(MinIoContentType.getContentType(originalFileName.substring(originalFileName.lastIndexOf("."))))
.build());
return new OssFile("agent-issues/" + appId + "/" + uuidFileName, originalFileName);
} catch (Exception e) {
log.error("MinIo 上传文件失败...{}", e.getMessage());
throw new GlobalException("MinIo 上传文件失败...请联系管理员");
}
}

private MinioClient minioBuild(ChannelModel data) {
return MinioClient.builder()
.endpoint(ossProperties.getEndpoint())
.credentials(data.getAccessKey(), data.getSecretKey())
.build();
}


/**
* 返回临时带签名、过期时间一天、Get请求方式的访问URL
*
* @param bucketName 桶名
* @param ossFilePath Oss文件路径
* @return 、
*/
public FileUrlVo getPresignedObjectUrl(String bucketName, String ossFilePath) {
try {
String imageUrl = minioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(bucketName)
.object(ossFilePath)
.expiry(60 * 60 * 24)
.build());
return new FileUrlVo(imageUrl);
} catch (Exception e) {
log.error("MinIo 访问文件URL临时路径失败...{}", e.getMessage());
throw new GlobalException("MinIo 访问文件URL临时路径失败...");
}
}

/**
* 生成随机文件名,防止重复
*
* @param originalFilename 原始文件名
* @return 、
*/
public String generateOssUuidFileName(String originalFilename, String busCode) {
// 原始文件名前加 24位uuid + "_"
String uuid = UUID.randomUUID().toString().replace("-", "").substring(0, 24);
if (!StringUtils.hasLength(busCode))
return DateUtil.format(new Date(), "yyyyMMdd") + StrUtil.SLASH + uuid + "_" + originalFilename;
else
return DateUtil.format(new Date(), "yyyyMMdd") + StrUtil.SLASH + busCode + StrUtil.SLASH + uuid + "_" + originalFilename;
}

/**
* 不处理文件名,重复
*
* @param originalFilename 原始文件名
* @return 、
*/
public String generateOssFileName(String originalFilename, String busCode) {
// 原始文件名前加 24位uuid + "_"
if (!StringUtils.hasLength(busCode))
return DateUtil.format(new Date(), "yyyyMMdd") + StrUtil.SLASH + originalFilename;
else
return DateUtil.format(new Date(), "yyyyMMdd") + StrUtil.SLASH + busCode + StrUtil.SLASH + originalFilename;
}

/**
* 初始化默认存储桶
*/
@PostConstruct
public void initDefaultBucket() {
String defaultBucketName = ossProperties.getDefaultBucketName();
if (bucketExists(defaultBucketName)) {
log.info("MinIo 默认存储桶已存在...无需创建");
return;
}
log.info("MinIo 创建默认存储桶...");
makeBucket(ossProperties.getDefaultBucketName());
}

public MinioClient getMinioClient() {
return minioClient;
}

public OssProperties getOssProperties() {
return ossProperties;
}

public void getPresignedObjectUrl(String appId, String key, String ossFilePath, HttpServletResponse response) {
List<ChannelPropertiesModel> jsonObject = JSONObject.parseArray(channelProperties.getChannelProperties(), ChannelPropertiesModel.class);
ChannelPropertiesModel imodel = null;
for (ChannelPropertiesModel model :
jsonObject) {
if (model.getAppId().equals(appId)) {
imodel = model;
}
}
if (imodel == null) {
throw new GlobalException("当前appId未授权");
}
if (!imodel.getData().getAccessKey().equals(key)) {
throw new GlobalException("key值校验失败,请输入正确的key");
}
ChannelModel data = imodel.getData();
MinioClient minioClient = minioBuild(data);
InputStream in = null;
ServletOutputStream out = null;
try {
String imageUrl = minioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket("agent-issues")
.object(appId + "/" + ossFilePath)
.expiry(60 * 60 * 24)
.build());
File file = getByFilePath(imageUrl);
MultipartFile multipartFile = convert(file);
// 获取文件的输入流
in = new FileInputStream(file);

// 推断文件的媒体类型
MediaType mediaType = MediaType.APPLICATION_OCTET_STREAM;
if (imageUrl.endsWith(".pdf")) {
mediaType = MediaType.APPLICATION_PDF;
} else if (imageUrl.endsWith(".jpg") || imageUrl.endsWith(".jpeg")) {
mediaType = MediaType.IMAGE_JPEG;
} else if (imageUrl.endsWith(".png")) {
mediaType = MediaType.IMAGE_PNG;
} else if (imageUrl.endsWith(".gif")) {
mediaType = MediaType.IMAGE_GIF;
}


// 设置响应头
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + file.getName());
response.setHeader(HttpHeaders.CONTENT_TYPE, mediaType.toString());
out = response.getOutputStream();
// 读取文件流
int len = 0;
byte[] buffer = new byte[1024 * 10];
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
// return new FileUrlVo(multipartFile);
} catch (Exception e) {
log.error("MinIo 访问文件URL临时路径失败...{}", e.getMessage());
throw new GlobalException("MinIo 访问文件URL临时路径失败...");
} finally {
try {
in.close();
out.close();
} catch (NullPointerException e) {
log.error("responseFileStream stream close() error:NullPointerException" + e.toString());
} catch (Exception e) {
log.error("responseFileStream stream close() error:" + e.toString());
}
}
}

private File getByFilePath(String imageUrl) {
String localFilePath = "/file.pdf"; // 替换为你想要保存的本地文件路径
try {
// 创建URL对象
URL url = new URL(imageUrl);
// 打开连接
URLConnection connection = url.openConnection();
// 获取输入流
InputStream inputStream = connection.getInputStream();

// 创建本地文件对象
File localFile = new File(localFilePath);
// 创建文件输出流
FileOutputStream outputStream = new FileOutputStream(localFile);

byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer))!= -1) {
outputStream.write(buffer, 0, bytesRead);
}

// 关闭资源
outputStream.close();
inputStream.close();

System.out.println("文件已成功保存到本地: " + localFilePath);
return localFile;
} catch (IOException e) {
e.printStackTrace();
throw new GlobalException("文件加载失败");
}
}

public MultipartFile convert(File file) throws IOException {
String fileName = file.getName();
String contentType = "application/octet-stream";


InputStream inputStream = new FileInputStream(file);


// 使用 MockMultipartFile 构造函数创建 MultipartFile
MultipartFile multipartFile = new MockMultipartFile(
fileName,
fileName,
contentType,
inputStream
);


return multipartFile;
}
}

+ 39
- 0
src/main/java/com/taiji/system/oss/MinioConfiguration.java 查看文件

@@ -0,0 +1,39 @@
package com.taiji.system.oss;

import io.minio.MinioClient;
import org.springframework.boot.autoconfigure.condition.*;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/***
* <p>
*
* </p>
* @author hou yi
* @date 2022/11/21 11:34
**/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({MinioClient.class})
@EnableConfigurationProperties(OssProperties.class)
@ConditionalOnExpression("${oss.enabled}")
@ConditionalOnProperty(value = "oss.type", havingValue = "minio")
public class MinioConfiguration {

@Bean
@ConditionalOnMissingBean(MinioClient.class)
public MinioClient minioClient(OssProperties ossProperties) {
return MinioClient.builder()
.endpoint(ossProperties.getEndpoint())
.credentials(ossProperties.getAccessKey(), ossProperties.getSecretKey())
.build();
}

@Bean
@ConditionalOnBean({MinioClient.class})
@ConditionalOnMissingBean(MinIoTemplate.class)
public MinIoTemplate minioTemplate(MinioClient minioClient, OssProperties ossProperties, ChannelProperties channelProperties) {
return new MinIoTemplate(minioClient, ossProperties, channelProperties);
}

}

+ 30
- 0
src/main/java/com/taiji/system/oss/OssFile.java 查看文件

@@ -0,0 +1,30 @@
package com.taiji.system.oss;

import io.swagger.annotations.ApiModelProperty;

/***
* <p>
*
* </p>
* @author hou yi
* @date 2022/11/21 10:59
**/
public class OssFile {
@ApiModelProperty("OSS 存储时文件路径")
private final String ossFilePath;
@ApiModelProperty("原始文件名")
private final String originalFileName;

public OssFile(String ossFilePath, String originalFileName) {
this.ossFilePath = ossFilePath;
this.originalFileName = originalFileName;
}

public String getOssFilePath() {
return ossFilePath;
}

public String getOriginalFileName() {
return originalFileName;
}
}

+ 93
- 0
src/main/java/com/taiji/system/oss/OssProperties.java 查看文件

@@ -0,0 +1,93 @@
package com.taiji.system.oss;

import com.taiji.system.enums.OssType;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/***
* <p>
*
* </p>
* @author hou yi
* @date 2022/11/21 11:02
**/
@Component
@ConfigurationProperties(prefix = "oss")
public class OssProperties {
/**
* 是否开启
*/
private Boolean enabled;

/**
* 存储对象服务器类型
*/
private OssType type;

/**
* OSS 访问端点,集群时需提供统一入口
*/
private String endpoint;
/**
* 用户名
*/
private String accessKey;

/**
* 密码
*/
private String secretKey;

/**
* 默认存储桶名,没有指定时,会放在默认的存储桶
*/
private String defaultBucketName;

public Boolean getEnabled() {
return enabled;
}

public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}

public OssType getType() {
return type;
}

public void setType(OssType type) {
this.type = type;
}

public String getEndpoint() {
return endpoint;
}

public void setEndpoint(String endpoint) {
this.endpoint = endpoint;
}

public String getAccessKey() {
return accessKey;
}

public void setAccessKey(String accessKey) {
this.accessKey = accessKey;
}

public String getSecretKey() {
return secretKey;
}

public void setSecretKey(String secretKey) {
this.secretKey = secretKey;
}

public String getDefaultBucketName() {
return defaultBucketName;
}

public void setDefaultBucketName(String defaultBucketName) {
this.defaultBucketName = defaultBucketName;
}
}

+ 16
- 0
src/main/java/com/taiji/system/util/GlobalException.java 查看文件

@@ -0,0 +1,16 @@
package com.taiji.system.util;

/***
* <p>
* 自定义异常类
* </p>
* @author hou yi
* @date 2022/11/22 16:58
**/
public class GlobalException extends RuntimeException {

public GlobalException(String msg) {
super(msg);
}

}

+ 44
- 0
src/main/java/com/taiji/system/util/GlobalExceptionHandle.java 查看文件

@@ -0,0 +1,44 @@
package com.taiji.system.util;

import com.taiji.system.enums.ResultStatusEnum;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

/***
* <p>
* 全局异常处理
* </p>
* @author hou yi
* @date 2022/7/27 11:17
**/
@RestControllerAdvice
@SuppressWarnings("all")
public class GlobalExceptionHandle extends ResponseEntityExceptionHandler {

@ExceptionHandler(RuntimeException.class)
public ResultWrapper<Object> customException(RuntimeException e) {
// 全局异常处理
return new ResultWrapper(ResultStatusEnum.GLOBAL_EXCEPTION.getCode(), e.getMessage(), null);
}

@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers,
HttpStatus status, WebRequest request) {
// 参数校验异常统一处理
final StringBuilder builder = new StringBuilder();
for (FieldError fieldError : ex.getBindingResult().getFieldErrors()) {
final String message = fieldError.getDefaultMessage();
builder.append(message);
break;
}
return ResponseEntity.ok(new ResultWrapper(ResultStatusEnum.PARAMETER_ERROR.getCode(), builder.toString(), null));
}

}

+ 98
- 0
src/main/java/com/taiji/system/util/ResultWrapper.java 查看文件

@@ -0,0 +1,98 @@
package com.taiji.system.util;

import com.taiji.system.enums.ResultStatusEnum;
import io.swagger.annotations.ApiModelProperty;

import java.io.Serializable;

/***
* <p>
* 接口、异常返回格式封装类
* </p>
* @author hou yi
* @date 2022/7/27 11:13
**/
public class ResultWrapper<T> implements Serializable {

@ApiModelProperty("状态码")
private Integer code;

@ApiModelProperty("提示语")
private String msg;

/*** 返回数据 */
private T data;

public ResultWrapper() {
}

public ResultWrapper(Integer code, String msg, T data) {
this.code = code;
this.msg = msg;
this.data = data;
}

/***
* 请求成功。有返回数据值
* @return 、
*/
public static <T> ResultWrapper<T> success(T t) {
return new ResultWrapper<T>(ResultStatusEnum.SUCCESS.getCode(), ResultStatusEnum.SUCCESS.getMessage(), t);
}

/***
* 请求成功。无返回数据值
* @return 、
*/
public static <T> ResultWrapper<T> success() {
return new ResultWrapper<T>(ResultStatusEnum.SUCCESS.getCode(), ResultStatusEnum.SUCCESS.getMessage(), null);
}

/***
* 请求失败。有返回数据值
* @return 、
*/
public static <T> ResultWrapper<T> fail(T t) {
return new ResultWrapper<T>(ResultStatusEnum.FAIL.getCode(), ResultStatusEnum.FAIL.getMessage(), t);
}

/***
* 请求失败。
* @return 、
*/
public static <T> ResultWrapper<T> fail(int code, String msg) {
return new ResultWrapper<T>(code, msg, null);
}

/***
* 请求失败。无返回数据值
* @return 、
*/
public static <T> ResultWrapper<T> fail() {
return new ResultWrapper<T>(ResultStatusEnum.FAIL.getCode(), ResultStatusEnum.FAIL.getMessage(), null);
}

public Integer getCode() {
return code;
}

public void setCode(Integer code) {
this.code = code;
}

public String getMsg() {
return msg;
}

public void setMsg(String msg) {
this.msg = msg;
}

public T getData() {
return data;
}

public void setData(T data) {
this.data = data;
}
}

+ 9
- 0
src/main/resources/application-dev.yml 查看文件

@@ -0,0 +1,9 @@
swagger:
enabled: true
oss:
enabled: true
type: MINIO
endpoint: http://159.75.82.245:9000
access-key: BW4NWYGOR1hL7RVi
secret-key: LhsZFNfl6ZQgFPNRDUu3HnCU3H37wFgq
default-bucket-name: default-bucket

+ 18
- 0
src/main/resources/application-prod.yml 查看文件

@@ -0,0 +1,18 @@
swagger:
enabled: true
oss:
enabled: true
type: MINIO
# 云服务器
# endpoint: http://162.14.66.140:9000
# access-key: dBiZy031W5Jrx2tF
# secret-key: 6FtjzfA7VlvcNYAFChSPrIY8M5GJgNcF
# default-bucket-name: default-bucket

# 内网
endpoint: http://100.64.2.113:9000
access-key: GtqvpOTqhWe4NRMr
secret-key: 7y4oeNnV8AcPqOopq9VS3lTC2EdQUFAc
default-bucket-name: default-bucket
channel:
channelProperties: {["appId": "52188938", "data": {"accessKey": "ngHXrWydteDe2L17","SecretKey": "6nIZwuHr9d2kYnNUJXTVTRLKLAE6EvUO","bucketName": "agent-issues"}], ["appId": "52188919", "data": {"accessKey": "9ui9dR6auFRFlN8d","SecretKey": "BqVD75Sm0uiWI7OyZLl7jXkM80YpYZ6D","bucketName": "agent-issues"}], ["appId": "52106998", "data": {"accessKey": "zt2LEYdnJ3GEYDX9","SecretKey": "dGYME50FgvV07aa7cB8MZy3xrAyya9Lm","bucketName": "agent-issues"}]}

+ 11
- 0
src/main/resources/application.yml 查看文件

@@ -0,0 +1,11 @@
server:
port: 6001

spring:
profiles:
active: prod
servlet:
multipart:
# 设置文件大小
max-file-size: 100MB
max-request-size: 100MB

+ 13
- 0
src/test/java/com/taiji/system/FileSystemApplicationTests.java 查看文件

@@ -0,0 +1,13 @@
package com.taiji.system;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class FileSystemApplicationTests {

@Test
void contextLoads() {
}

}

Loading…
取消
儲存