说明:本文章是springboot和minio的整合,同时还有上传和下载工具类,minio的具体介绍这里就不多说了【上传和下载都是基础工具类, minio的安装如果有时间就更新】
工程图:【主要功能在于工具类,在代码块11和12标红代码】
1.pom.xml 文件
<?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>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>server-file</groupId>
<artifactId>server-file</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>server-file Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<!-- swagger -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>2.0.9</version>
</dependency>
<!--minio 对象存储 -->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.3.1</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.9.2</version>
</dependency>
<!-- 引入 json -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.28</version>
</dependency>
</dependencies>
<build>
<finalName>server-file</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.5.9.RELEASE</version>
<configuration>
<mainClass>com.file.App</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
2.application.yml 文件
server:
port: 8080
servlet:
context-path: /server-file
minio:
endpoint: http://127.0.0.1:9000
accesskey: minioadmin
secretKey: minioadmin
3.MinioConfiguration.java文件
package com.file.conf;
import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MinioConfiguration {
@Value("${minio.endpoint}")
private String endpoint;
@Value("${minio.accesskey}")
private String accesskey;
@Value("${minio.secretKey}")
private String secretKey;
@Bean
public MinioClient minioClient() {
return MinioClient.builder()
.endpoint(endpoint)
.credentials(accesskey, secretKey)
.build();
}
}
4.SwaggerConfig.java文件
package com.file.conf;
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
import java.util.ArrayList;
import java.util.List;
/**
* @author 李庆伟
* @date 2022/5/20 10:22
*/
@ConditionalOnWebApplication
@Configuration
@EnableSwagger2WebMvc
@EnableKnife4j
public class SwaggerConfig {
/**
* Swagger2的配置文件,这里可以配置Swagger2的一些基本的内容,比如扫描的包等等
* []
* @return {@link Docket}
* @throws
* @author 李庆伟
* @date 2021/12/13 16:28
*/
@Bean
public Docket createRestApi() {
//设置请求在父类方法中,如果在本类方法中设置请求头,则覆盖父类方法
List<Parameter> pars = makeHeader();
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage(makeScan()))
//.apis(RequestHandlerSelectors.basePackage(App8300.class.getPackage().getName()))
.build()
.globalOperationParameters(pars)
.apiInfo(apiInfo());
}
/**
* swagger封装请求头
* [pars]
* @return {@link List< Parameter>}
* @throws
* @author 李庆伟
* @date 2022/5/20 11:26
*/
public List<Parameter> makeHeader(){
List<Parameter> pars = new ArrayList<>();
ParameterBuilder token = new ParameterBuilder();
token.name("Authorization").description("Authorization")
.modelRef(new ModelRef("string"))
.parameterType("header")
.required(false).build();
pars.add(token.build());
ParameterBuilder languageCode = new ParameterBuilder();
languageCode.name("languageCode").description("languageCode")
.modelRef(new ModelRef("string"))
.parameterType("header")
.required(false).build();
pars.add(languageCode.build());
return pars;
}
public String makeScan(){
return "com.file.controller";
}
/**
* 构建API文档的详细信息函数
* @return
*/
public ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title(makeApiName())
.version("1.0")
.build();
}
public String makeApiName(){
return "文档服务接口-API";
}
}
5.MyException.java文件
package com.file.exceptions;
/**
* @author 李庆伟
* @date 2020/4/16 10:10
*/
public class MyException extends RuntimeException{
private int code;
private String msg;
public MyException(int code, String msg){
super(msg);
this.code = code;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}
6.TopException.java文件
package com.file.exceptions;
import com.file.results.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @author 李庆伟
* @date 2020/4/16 10:11
*/
@ControllerAdvice
public class TopException {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@ExceptionHandler(value = MyException.class)
@ResponseBody
public Result myExceptionHandle(Exception e){
MyException myException = (MyException) e;
return Result.error(myException.getCode(),myException.getMessage());
}
//此异常放在最下面,当所有异常都检查不到的时候会进入该异常
@ExceptionHandler(value = Exception.class)
@ResponseBody
public Result handle(Exception e){
logger.error("系统日志",e);
return Result.error(1000,"RETURN_FAIL");
}
}
7.Result.java文件
package com.file.results;
import com.alibaba.fastjson.JSON;
import com.file.util.LanguageUtil;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.servlet.ServletResponse;
import java.io.PrintWriter;
import java.util.List;
/**
* @author 李庆伟
* @date 2020/4/16 9:52
*/
@Data
public class Result {
@ApiModelProperty(value = "返回码")
private int code;
@ApiModelProperty(value = "返回数据")
private Object data;
@ApiModelProperty(value = "返回描述")
private String msg;
@ApiModelProperty(value = "返回长度")
private long count;
/**返回成功 */
public static Result success(List<Object> data, long count){
Result result = new Result();
result.setCode(0);//成功
result.setMsg(LanguageUtil.getMessage("RETURN_SUCCESS"));//提示语
result.setData(data);
result.setCount(count);
return result;
}
/**返回成功 */
public static Result success(List data){
Result result = new Result();
result.setCode(0);//成功
result.setMsg(LanguageUtil.getMessage("RETURN_SUCCESS"));//提示语
result.setData(data);
result.setCount(data == null || data.size() == 0 ? 0 : data.size());
return result;
}
/**返回成功 */
public static Result successForPage(List data, Integer count){
Result result = new Result();
result.setCode(0);//成功
result.setMsg(LanguageUtil.getMessage("RETURN_SUCCESS"));//提示语
result.setData(data);
result.setCount(count == null ? 0 : count);
return result;
}
/**返回成功 */
public static Result success(){
Result result = new Result();
result.setCode(0);//成功
result.setMsg(LanguageUtil.getMessage("RETURN_SUCCESS"));//提示语
return result;
}
/**返回成功 */
public static Result success(Object object){
Result result = new Result();
result.setCode(0);//成功
result.setMsg(LanguageUtil.getMessage("RETURN_SUCCESS"));//提示语
result.setData(object);//返回内容
return result;
}
/**返回失败 */
public static Result error(){
Result result = new Result();
result.setCode(1);//失败
result.setMsg(LanguageUtil.getMessage("RETURN_FAIL"));//提示语
return result;
}
/**返回失败 */
public static Result error(int code, String msg){
Result result = new Result();
result.setCode(code);//失败
result.setMsg(LanguageUtil.getMessage(msg));//提示语
return result;
}
/**Response输出Json格式 */
public static void responseJson(ServletResponse response, Object data) {
PrintWriter out = null;
try {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
out = response.getWriter();
out.println(JSON.toJSONString(data));
out.flush();
} catch (Exception e) {
System.out.println("Response输出Json异常:" + e);
} finally {
if (out != null) {
out.close();
}
}
}
/**返回信息*/
public static Result response(int code, String msg, Object data) {
Result result = new Result();
result.setCode(code);
result.setMsg(msg);
result.setData(data);
return result;
}
}
8.LanguageUtil.java文件
package com.file.util;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;
/**
* 多语言工具类
* @author 李庆伟
* @date 2022/5/12 15:57
*/
@Component
public class LanguageUtil {
private static List<String> languages = Arrays.asList("en-US","fr-FR","zh-CN");
private static HashMap<String, Properties> mapProperties = new HashMap<>();
static {
for(String s:languages){
mapProperties.put(s,new Properties());
}
for(String s:languages){
String messageConfigFile = String.format("MessageConfig_%s.properties",s);
InputStream ios = LanguageUtil.class.getClassLoader().getResourceAsStream(messageConfigFile);
if(ios != null){
try {
mapProperties.get(s).load(ios);
} catch (IOException e) {
throw new RuntimeException("could not find Properties ==> "+ messageConfigFile);
}finally {
try {
ios.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
/**
* 根据key获取.properties文件中的value
* [key]
* @return {@link String}
* @throws
* @author 李庆伟
* @date 2022/7/14 10:06
*/
public static String getMessage(String key){
//HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//language = request.getHeader("languageCode");
String language = getHeaderLanguages();
if(StringUtils.isEmpty(language)){
language = "en-US";
} else{
if(!language.equals("fr-FR") && !language.equals("zh-CN")){
language = "en-US";
}
}
String strMessage = "";
if(StringUtils.isNotEmpty(key) && mapProperties.get(language) != null){
strMessage = mapProperties.get(language).getProperty(key);
if(StringUtils.isEmpty(strMessage)){
strMessage = key;
}
}
return strMessage;
}
public static String getMessagEn(String key){
String language = "en-US";
String strMessage = "";
if(StringUtils.isNotEmpty(key) && mapProperties.get(language) != null){
strMessage = mapProperties.get(language).getProperty(key);
if(StringUtils.isEmpty(strMessage)){
strMessage = key;
}
}
return strMessage;
}
/**
* 从请求头中获取多语言类型
* []
* @return {@link String}
* @throws
* @author 李庆伟
* @date 2022/7/14 10:04
*/
public static String getHeaderLanguages(){
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
String language = request.getHeader("languageCode");
return language;
}
/**
* 返回国际化展示字段
* [chineseName, englishName, frenchName]
* [name]
* @return {@link String}
* @throws
* @author 李庆伟
* @date 2022/7/14 10:05
*/
public static String getDisplayName(String... name) {
String language = getHeaderLanguages();
if(StringUtils.isEmpty(language)){
return name[1];
}
switch (language){
case "en-US":
return name[1];
case "fr-FR":
return name[2];
case "zh-CN":
return name[0];
}
return name[1];
}
}
9.App.java文件
package com.file;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
10.UpResModel.java文件
package com.file.model;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author 李庆伟
* @date 2023/2/13 16:51
*/
@Data
public class UpResModel {
@ApiModelProperty(name = "fileName",value = "文件原始名称")
private String fileName;
@ApiModelProperty(name = "filePath",value = "文件内部路径:/桶/文件夹/文件名称")
private String filePath;
@ApiModelProperty(name = "visitFilePath",value = "外部访问路径:开发阶段可以自己测试,不可用于线上,有效时间60个小时")
private String visitFilePath;
}
11.BucketUtil.java文件
package com.file.util;
import com.file.exceptions.MyException;
import io.minio.BucketExistsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.RemoveBucketArgs;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 桶工具类封装
* @author 李庆伟
* @date 2023/2/9 16:39
*/
@Component
public class BucketUtil {
@Autowired
private MinioClient client;
/**
* 添加桶
* [client, bucketName]
* @return {@link }
* @throws
* @author 李庆伟
* @date 2023/2/9 16:44
*/
public void add(String bucketName) {
try {
boolean isExist = exist(bucketName);
if (!isExist) {
client.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
}
} catch (Exception e) {
throw new MyException(1000,"BUCKET_ADD_FAIL");
}
}
/**
* 删除桶
* [client, bucketName]
* @return {@link }
* @throws
* @author 李庆伟
* @date 2023/2/9 16:45
*/
public void delete(String bucketName) {
try {
boolean isExist = exist(bucketName);
if (isExist) {
client.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
}
} catch (Exception e) {
throw new MyException(1000,"BUCKET_DELETE_FAIL");
}
}
/**
* 判断桶是否存在
* [client, bucketName]
* @return {@link boolean}
* @throws
* @author 李庆伟
* @date 2023/2/9 16:42
*/
public boolean exist(String bucketName) {
try {
return client.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
}
12.FileUtil.java文件
package com.file.util;
import com.file.exceptions.MyException;
import com.file.model.UpResModel;
import com.google.common.io.ByteStreams;
import io.minio.*;
import io.minio.http.Method;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.apache.commons.lang.StringUtils;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Optional;
/**
* 文件管理工具类
*
* @return {@link }
* @throws
* @author 李庆伟
* @date 2023/2/13 11:40
*/
@Component
public class FileUtil {
@Autowired
private MinioClient client;
/**
* 上传文件【不带文件夹】
* [file, bucketName]
* file:文件
* bucketName:桶
* @return {@link Map< String, String>}
* @throws
* @author 李庆伟
* @date 2023/2/10 13:59
*/
public UpResModel upload(MultipartFile file, String bucketName, String lastName) {
return upload(file,bucketName,null,lastName);
}
/**
* 上传文件【带文件夹】
* [client, file, bucketName, folderName]
* file:文件
* bucketName:桶
* folderName:文件夹
* lastName:
* 注:因为文件重复覆盖问题,所有的文件上传前都会更改文件名称 即 原来文件名+_+33位随机字符+文件后缀
* 例如:a.txt 上传后是 a_12....33.txt
* @return {@link Map< String, String>}
* fileName:原始文件名称
* filePath:桶+文件夹+文件
* visitFilePath:外部访问地址
* @throws
* @author 李庆伟
* @date 2023/2/10 14:00
*/
public UpResModel upload(MultipartFile file, String bucketName, String folderName, String lastName) {
//判断桶是否存在
boolean be = exist(bucketName);
if(!be){
throw new MyException(404,"BUCKET_NOT_FIND");
}
InputStream inputStream = null;
try {
inputStream = file.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
folderName = Optional.ofNullable(folderName).orElse("");
if(!"".equals(folderName)){
folderName = "/"+ folderName;
}
//原始名称
String fileName = file.getOriginalFilename();
String minFileName = folderName + "/" + lastName;
//上传文件到指定目录
try {
client.putObject(PutObjectArgs.builder()
.bucket(bucketName)
.object(minFileName)
.contentType(file.getContentType())
.stream(inputStream, inputStream.available(), -1)
.build());
inputStream.close();
} catch (Exception e) {
throw new MyException(500,"FILE_UPLOAD_FAIL");
}
// 返回件访问路径
/*
Map<String,String> map = new HashMap<>();
map.put("fileName",fileName);
map.put("filePath","/" + bucketName + minFileName);
map.put("visitFilePath",getObjectUrl(bucketName, minFileName));
return map;
*/
UpResModel u = new UpResModel();
u.setFileName(fileName);
u.setFilePath("/" + bucketName + minFileName);
u.setVisitFilePath(getObjectUrl(bucketName, minFileName));
return u;
}
/**
* 对外连接
* [client, bucketName, minFileName]
* bucketName:桶
* minFileName:文件夹路径+文件名
* @return {@link String}
* @throws
* @author 李庆伟
* @date 2023/2/10 14:01
*/
@SneakyThrows
public String getObjectUrl(String bucketName, String minFileName) {
//expiry = expiryHandle(expiry);
return client.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(bucketName)
.object(minFileName)
.expiry(60*60)//过期时间(分钟数)
.build()
);
}
/**
* 单文件下载
* [client, response, filePath]
* @return {@link }
* @throws
* @author 李庆伟
* @date 2023/2/13 11:33
*/
public void download(HttpServletResponse response, String bucketName, String pathName, String downName) {
if(bucketName == null || pathName == null || downName == null ||
StringUtils.isEmpty(bucketName) || StringUtils.isEmpty(pathName) || StringUtils.isEmpty(downName)){
throw new MyException(404,"BUCKET_NOT_FIND");
}
try (
ServletOutputStream os = response.getOutputStream();
GetObjectResponse is = downloadOne(bucketName, pathName)
) {
response.setCharacterEncoding("utf-8");
response.setContentType("APPLICATION/OCTET-STREAM");
response.addHeader("Content-Disposition", "attachment;filename=" + downName);
ByteStreams.copy(is, os);
os.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 删除文件
* [bucketName, pathName]
* @return {@link boolean}
* @throws
* @author 李庆伟
* @date 2023/2/13 16:14
*/
@SneakyThrows
public boolean deleteFile(String bucketName, String pathName) {
if (!exist(bucketName)) {
return false;
}
client.removeObject(
RemoveObjectArgs.builder()
.bucket(bucketName)
.object(pathName)
.build());
return true;
}
@SneakyThrows
public GetObjectResponse downloadOne(String bucketName,String objectName) {
GetObjectArgs getObjectArgs = GetObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.build();
return client.getObject(getObjectArgs);
}
public boolean exist(String bucketName) {
try {
return client.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
}
13.BucketController.java文件
package com.file.controller;
import com.file.results.Result;
import com.file.service.BucketService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* @author 李庆伟
* @date 2023/2/9 11:07
*/
@RestController
@RequestMapping("/bucket")
@Api(value = "文件存储桶服务", tags = "文件存储桶服务")
public class BucketController {
@Autowired
private BucketService bucketService;
/**
* 桶添加
* @return {@link }
* @throws
* @author
* @date
*/
@PostMapping(value = "/add")
@ApiOperation(value = "桶添加", notes = "桶添加", produces = "application/json")
public Result add(@ApiParam(required = true, value = "bucketName") @RequestParam(value = "bucketName", required = true) String bucketName) {
bucketService.add(bucketName);
return Result.success();
}
/**
* 桶删除
* @return {@link }
* @throws
* @author
* @date
*/
@PostMapping(value = "/delete")
@ApiOperation(value = "桶删除", notes = "桶删除", produces = "application/json")
public Result delete(@ApiParam(required = true, value = "bucketName") @RequestParam(value = "bucketName", required = true) String bucketName) {
bucketService.delete(bucketName);
return Result.success();
}
/**
* 桶是否存在
* @return {@link }
* @throws
* @author
* @date
*/
@PostMapping(value = "/exist")
@ApiOperation(value = "桶是否存在", notes = "桶是否存在", produces = "application/json")
public Result exist(@ApiParam(required = true, value = "bucketName") @RequestParam(value = "bucketName", required = true) String bucketName) {
return Result.success(bucketService.exist(bucketName));
}
}
14.BucketService.java文件
package com.file.service;
/**
*
* @return {@link }
* @throws
* @author
* @date 2023/2/9 11:28
*/
public interface BucketService {
//桶添加
void add(String bucketName);
//桶删除
void delete(String bucketName);
//桶是否存在
boolean exist(String bucketName);
}
15.BucketServiceImpl.java文件
package com.file.service.impl;
import com.file.service.BucketService;
import com.file.util.BucketUtil;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class BucketServiceImpl implements BucketService {
@Resource
private BucketUtil bucketUtil;
/**
* 桶添加
* [bucketName]
* @return {@link }
* @throws
* @date 2023/2/9 11:29
*/
public void add(String bucketName) {
bucketUtil.add(bucketName);
}
/**
* 桶删除
* [bucketName]
* @return {@link }
* @throws
* @date 2023/2/9 11:29
*/
public void delete(String bucketName) {
bucketUtil.delete(bucketName);
}
/**
* 桶是否存在
* [bucketName]
* @return {@link }
* @throws
* @date 2023/2/9 11:29
*/
public boolean exist(String bucketName) {
return bucketUtil.exist(bucketName);
}
}
16.FileController.java文件
package com.file.controller;
import com.file.model.UpResModel;
import com.file.results.Result;
import com.file.service.FileService;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
/**
*
* @author 李庆伟
* @date 2023/2/9 16:09
*/
@RestController
@RequestMapping("/file")
@Api(value = "文件操作服务", tags = "文件操作服务")
public class FileController {
@Autowired
private FileService fileService;
/**
* 单文件上传
* [file, bucketName]
* file:文件流
* bucketName:桶名称
* folderName:文件夹路径
* 例如:上传到桶[tong]下文件夹[/a/b/c]
* @return {@link Result}
* @throws
* @author 李庆伟
* @date 2023/2/9 16:25
*/
@PostMapping(value = "/upload")
@ApiOperation(value = "单文件上传", notes = "单文件上传")
@ApiResponses({
@ApiResponse(code = 0, message = "ok", response= UpResModel.class),
})
public Result upload(@RequestParam(value = "file") MultipartFile file,
@ApiParam(required = true, value = "bucketName") @RequestParam(value = "bucketName", required = true) String bucketName,
@ApiParam(required = false, value = "folderName") @RequestParam(value = "folderName", required = false) String folderName
){
UpResModel map = fileService.upload(file, bucketName, folderName);
//超过5M的文件不进行转换
return Result.success(map);
}
/**
* 单文件下载
* [response, filePath]
* filePath格式:/桶/文件夹1/文件夹2.../文件名称
* 例如:/tong/a/b/c/d.txt
* @return {@link }
* @throws
* @author 李庆伟
* @date 2023/2/10 14:39
*/
@GetMapping("/download")
@ApiOperation(value = "单文件下载", notes = "单文件下载", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public void download(HttpServletResponse response, @ApiParam(required = true, value = "filePath") @RequestParam("filePath")String filePath){
fileService.download(response,filePath);
}
/**
* 删除文件
* [filePath]
* filePath格式:/桶/文件夹1/文件夹2.../文件名称
* 例如:/tong/a/b/c/d.txt
* @return {@link Result}
* @throws
* @author 李庆伟
* @date 2023/2/13 15:42
*/
@DeleteMapping("/delete")
@ApiOperation(value = "文件删除", notes = "文件删除")
public Result delete(@ApiParam(required = true, value = "filePath") @RequestParam("filePath")String filePath) {
return Result.success(fileService.delete(filePath));
}
}
17.FileService.java文件
package com.file.service;
import com.file.model.UpResModel;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
/**
*
* @return {@link }
* @throws
* @author
* @date 2023/2/9 11:28
*/
public interface FileService {
//单文件上传
UpResModel upload(MultipartFile file, String bucketName, String folderName);
//单文件下载
void download(HttpServletResponse response, String fileName);
//删除文件
boolean delete(String filePath);
}
18.FileServiceImpl.java文件
package com.file.service.impl;
import com.file.exceptions.MyException;
import com.file.model.UpResModel;
import com.file.service.FileService;
import com.file.util.FileUtil;
import lombok.SneakyThrows;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.UUID;
@Service
public class FileServiceImpl implements FileService {
@Resource
private FileUtil fileUtil;
/**
* 单文件上传
* [file, bucketName]
* @return {@link Map< String, String>}
* @throws
* @author 李庆伟
* @date 2023/2/9 16:27
*/
public UpResModel upload(MultipartFile file, String bucketName, String folderName) {
//原始名称
String fileName = file.getOriginalFilename();
int len = fileName.lastIndexOf(".");
String lastName = "";
//原始文件名_随机字符串
if(len != -1){
lastName = fileName.substring(0,len) + "_" +
UUID.randomUUID().toString().replace("-","") +
fileName.substring(len,fileName.length());
} else {
lastName = fileName+ "_" + UUID.randomUUID().toString().replace("-","");
}
UpResModel upResModel = fileUtil.upload(file, bucketName, folderName, lastName);
return upResModel;
}
/**
* 单文件下载
* [response, fileName]
* @return {@link }
* @throws
* @author 李庆伟
* @date 2023/2/10 14:40
*/
public void download(HttpServletResponse response,final String filePath) {
if(filePath == null || StringUtils.isEmpty(filePath)){
throw new MyException(404,"BUCKET_NOT_FIND");
}
String bucketName = filePath.split("/")[1];
String pathName = filePath.replace("/"+bucketName,"");
String fileName = "";
String [] arr = filePath.split("/");
String name = arr[arr.length-1];
int m = name.lastIndexOf("_");
int n = name.lastIndexOf(".");
if(m != -1 && n != -1 && n-m == 33){
String prefixName = name.substring(0,m);
String suffixName = name.substring(n,name.length());
fileName = prefixName+suffixName;
} else if (m != -1 && n == -1 && name.substring(m,name.length()).length() == 33){
fileName = name.substring(0,m);
} else {
fileName = name;
}
fileUtil.download(response,bucketName,pathName,fileName);
}
/**
* 删除文件
* [filePath]
* @return {@link boolean}
* @throws
* @author 李庆伟
* @date 2023/2/13 15:43
*/
@SneakyThrows
public boolean delete(String filePath) {
String bucketName = filePath.split("/")[1];
String pathName = filePath.replace("/"+bucketName,"");
return fileUtil.deleteFile(bucketName,pathName);
}
}
19.MessageConfig_zh-CN.properties,MessageConfig_en-US.properties,MessageConfig_fr-FR.properties文件 三个文件中的内容都一样
#public
RETURN_SUCCESS = 成功!
RETURN_FAIL = 失败!
BUCKET_NOT_FIND = 桶不存在.
FILE_UPLOAD_FAIL = 文件上传失败.
内容比较简单,到此结束。。。。。