From 52aa611a1d2794b5613bfb5676c92746bd1f5e88 Mon Sep 17 00:00:00 2001 From: XSWL1018 <824576966@qq.com> Date: Mon, 17 Jun 2024 12:23:59 +0800 Subject: [PATCH 1/7] init --- .../controller/common/CommonController.java | 52 +-- .../system/SysProfileController.java | 67 ++-- .../main/resources/application-middleware.yml | 12 +- .../src/main/resources/application.yml | 2 + .../com/ruoyi/common/config/RuoYiConfig.java | 15 +- .../ruoyi/common/utils/file/DiskFileUtil.java | 104 ++++++ .../common/utils/file/FileOperateUtils.java | 103 ++++++ .../common/utils/file/FileTypeUtils.java | 9 +- .../common/utils/file/FileUploadUtils.java | 232 ------------- .../com/ruoyi/common/utils/file/FileUtil.java | 77 +++++ .../ruoyi/common/utils/file/FileUtils.java | 313 ++++++++++++------ .../ruoyi/common/utils/file/ImageUtils.java | 15 +- .../minio/config/MinioClientConfig.java | 103 ++++++ .../middleware/minio/config/MinioConfig.java | 96 +++--- .../minio/controller/MinioController.java | 50 +-- .../middleware/minio/domain/MinioFileVO.java | 68 ++++ .../exception/MinioClientErrorException.java | 7 + .../MinioClientNotFundException.java | 4 + .../minio/utils/FileUploadMinioUtils.java | 84 ----- .../middleware/minio/utils/MinioFileUtil.java | 66 ++++ .../middleware/minio/utils/MinioUtil.java | 297 +++++++++++++++-- 21 files changed, 1163 insertions(+), 613 deletions(-) create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/file/DiskFileUtil.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileOperateUtils.java delete mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtil.java create mode 100644 ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/config/MinioClientConfig.java create mode 100644 ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/domain/MinioFileVO.java create mode 100644 ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/exception/MinioClientErrorException.java create mode 100644 ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/exception/MinioClientNotFundException.java delete mode 100644 ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/utils/FileUploadMinioUtils.java create mode 100644 ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/utils/MinioFileUtil.java diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java index d966ad8..61bef95 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java @@ -1,27 +1,14 @@ package com.ruoyi.web.controller.common; -import java.util.ArrayList; -import java.util.List; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.MediaType; -import org.springframework.web.bind.annotation.GetMapping; -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; -import org.springframework.web.multipart.MultipartFile; - +import com.ruoyi.common.annotation.Anonymous; import com.ruoyi.common.config.RuoYiConfig; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.file.FileUploadUtils; +import com.ruoyi.common.utils.file.FileOperateUtils; import com.ruoyi.common.utils.file.FileUtils; +import com.ruoyi.common.utils.file.MimeTypeUtils; import com.ruoyi.framework.config.ServerConfig; - import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; @@ -29,10 +16,19 @@ import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +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 java.util.ArrayList; +import java.util.List; /** * 通用请求处理 - * + * * @author ruoyi */ @Tag(name = "通用请求处理") @@ -48,7 +44,7 @@ public class CommonController { /** * 通用下载请求 - * + * * @param fileName 文件名称 * @param delete 是否删除 */ @@ -58,6 +54,7 @@ public class CommonController { @Parameter(name = "delete", description = "是否删除") }) @GetMapping("/download") + @Anonymous public void fileDownload( @RequestParam("fileName") String fileName, @RequestParam("delete") Boolean delete, @@ -72,9 +69,10 @@ public class CommonController { response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); FileUtils.setAttachmentResponseHeader(response, realFileName); - FileUtils.writeBytes(filePath, response.getOutputStream()); + // FileUtils.writeBytes(filePath, response.getOutputStream()); + FileOperateUtils.downLoad(filePath, response.getOutputStream()); if (delete) { - FileUtils.deleteFile(filePath); + FileOperateUtils.deleteFile(fileName); } } catch (Exception e) { log.error("下载文件失败", e); @@ -86,12 +84,13 @@ public class CommonController { */ @Operation(summary = "通用上传请求(单个)") @PostMapping("/upload") + @Anonymous public AjaxResult uploadFile(@RequestBody MultipartFile file) throws Exception { try { // 上传文件路径 - String filePath = RuoYiConfig.getUploadPath(); + // String filePath = RuoYiConfig.getUploadPath(); // 上传并返回新文件名称 - String fileName = FileUploadUtils.upload(filePath, file); + String fileName = FileOperateUtils.upload(file); String url = serverConfig.getUrl() + fileName; AjaxResult ajax = AjaxResult.success(); ajax.put("url", url); @@ -109,6 +108,7 @@ public class CommonController { */ @Operation(summary = "通用上传请求(多个)") @PostMapping("/uploads") + @Anonymous public AjaxResult uploadFiles(@RequestBody List files) throws Exception { try { @@ -120,7 +120,7 @@ public class CommonController { List originalFilenames = new ArrayList(); for (MultipartFile file : files) { // 上传并返回新文件名称 - String fileName = FileUploadUtils.upload(filePath, file); + String fileName = FileOperateUtils.upload(filePath, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION); String url = serverConfig.getUrl() + fileName; urls.add(url); fileNames.add(fileName); @@ -143,6 +143,7 @@ public class CommonController { */ @Operation(summary = "本地资源通用下载") @GetMapping("/download/resource") + @Anonymous public void resourceDownload(@Parameter(name = "resource", description = "资源名称") String resource, HttpServletRequest request, HttpServletResponse response) throws Exception { @@ -157,8 +158,9 @@ public class CommonController { // 下载名称 String downloadName = StringUtils.substringAfterLast(downloadPath, "/"); response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); - FileUtils.setAttachmentResponseHeader(response, downloadName); - FileUtils.writeBytes(downloadPath, response.getOutputStream()); + FileUtils.setAttachmentResponseHeader(response, resource); + FileOperateUtils.downLoad(resource, response.getOutputStream()); + // FileUtils.writeBytes(downloadPath, response.getOutputStream()); } catch (Exception e) { log.error("下载文件失败", e); } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java index 3e7e6d0..623009e 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java @@ -1,15 +1,5 @@ package com.ruoyi.web.controller.system; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.multipart.MultipartFile; - import com.ruoyi.common.annotation.Log; import com.ruoyi.common.config.RuoYiConfig; import com.ruoyi.common.core.controller.BaseController; @@ -19,24 +9,28 @@ import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.file.FileUploadUtils; +import com.ruoyi.common.utils.file.FileOperateUtils; +import com.ruoyi.common.utils.file.FileUtils; import com.ruoyi.common.utils.file.MimeTypeUtils; import com.ruoyi.framework.web.service.TokenService; import com.ruoyi.system.service.ISysUserService; - import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; /** * 个人信息 业务处理 - * + * * @author ruoyi */ -@Tag(name = "个人信息" , description = "业务处理") +@Tag(name = "个人信息", description = "业务处理") @RestController @RequestMapping("/system/user/profile") -public class SysProfileController extends BaseController -{ +public class SysProfileController extends BaseController { @Autowired private ISysUserService userService; @@ -48,8 +42,7 @@ public class SysProfileController extends BaseController */ @Operation(summary = "个人信息") @GetMapping - public AjaxResult profile() - { + public AjaxResult profile() { LoginUser loginUser = getLoginUser(); SysUser user = loginUser.getUser(); AjaxResult ajax = AjaxResult.success(user); @@ -64,25 +57,21 @@ public class SysProfileController extends BaseController @Operation(summary = "修改用户") @Log(title = "个人信息", businessType = BusinessType.UPDATE) @PutMapping - public AjaxResult updateProfile(@RequestBody SysUser user) - { + public AjaxResult updateProfile(@RequestBody SysUser user) { LoginUser loginUser = getLoginUser(); SysUser sysUser = loginUser.getUser(); user.setUserName(sysUser.getUserName()); - if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) - { + if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) { return error("修改用户'" + user.getUserName() + "'失败,手机号码已存在"); } - if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) - { + if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) { return error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在"); } user.setUserId(sysUser.getUserId()); user.setPassword(null); user.setAvatar(null); user.setDeptId(null); - if (userService.updateUserProfile(user) > 0) - { + if (userService.updateUserProfile(user) > 0) { // 更新缓存用户信息 sysUser.setNickName(user.getNickName()); sysUser.setPhonenumber(user.getPhonenumber()); @@ -100,22 +89,18 @@ public class SysProfileController extends BaseController @Operation(summary = "重置密码") @Log(title = "个人信息", businessType = BusinessType.UPDATE) @PutMapping("/updatePwd") - public AjaxResult updatePwd(String oldPassword, String newPassword) - { + public AjaxResult updatePwd(String oldPassword, String newPassword) { LoginUser loginUser = getLoginUser(); String userName = loginUser.getUsername(); String password = loginUser.getPassword(); - if (!SecurityUtils.matchesPassword(oldPassword, password)) - { + if (!SecurityUtils.matchesPassword(oldPassword, password)) { return error("修改密码失败,旧密码错误"); } - if (SecurityUtils.matchesPassword(newPassword, password)) - { + if (SecurityUtils.matchesPassword(newPassword, password)) { return error("新密码不能与旧密码相同"); } newPassword = SecurityUtils.encryptPassword(newPassword); - if (userService.resetUserPwd(userName, newPassword) > 0) - { + if (userService.resetUserPwd(userName, newPassword) > 0) { // 更新缓存用户密码 loginUser.getUser().setPassword(newPassword); tokenService.setLoginUser(loginUser); @@ -130,14 +115,14 @@ public class SysProfileController extends BaseController @Operation(summary = "头像上传") @Log(title = "用户头像", businessType = BusinessType.UPDATE) @PostMapping("/avatar") - public AjaxResult avatar(@RequestParam("avatarfile") MultipartFile file) throws Exception - { - if (!file.isEmpty()) - { + public AjaxResult avatar(@RequestParam("avatarfile") MultipartFile file) throws Exception { + if (!file.isEmpty()) { LoginUser loginUser = getLoginUser(); - String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file, MimeTypeUtils.IMAGE_EXTENSION); - if (userService.updateUserAvatar(loginUser.getUsername(), avatar)) - { + String extractPath = loginUser.getUsername() + File.separator + loginUser.getUserId(); + String fileName = "avatar." + FileUtils.getExtension(file); + String avatar = FileOperateUtils.upload(RuoYiConfig.getAvatarPath()+extractPath, fileName, file, + MimeTypeUtils.IMAGE_EXTENSION); + if (userService.updateUserAvatar(loginUser.getUsername(), avatar)) { AjaxResult ajax = AjaxResult.success(); ajax.put("imgUrl", avatar); // 更新缓存用户头像 diff --git a/ruoyi-admin/src/main/resources/application-middleware.yml b/ruoyi-admin/src/main/resources/application-middleware.yml index 118ed25..0b6534d 100644 --- a/ruoyi-admin/src/main/resources/application-middleware.yml +++ b/ruoyi-admin/src/main/resources/application-middleware.yml @@ -25,7 +25,11 @@ spring: # Minio配置 minio: - url: http://localhost:9000 - accessKey: minioadmin - secretKey: minioadmin - bucketName: ruoyi + enable: true + downLoadLimit: 1024 + client: + master: + url: http://localhost:9000 + accessKey: root + secretKey: 123456 + defaultBuket: ruoyi diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index 085340b..6b2d3c7 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -13,6 +13,8 @@ ruoyi: # 验证码类型 math 数组计算 char 字符验证 captchaType: math + fileServer: minio + # 开发环境配置 server: # 服务器的HTTP端口,默认为8080 diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java index 29281cf..24abfe2 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java @@ -5,7 +5,7 @@ import org.springframework.stereotype.Component; /** * 读取项目相关配置 - * + * * @author ruoyi */ @Component @@ -24,12 +24,17 @@ public class RuoYiConfig /** 上传路径 */ private static String profile; + + + private static String fileServer; + /** 获取地址开关 */ private static boolean addressEnabled; /** 验证码类型 */ private static String captchaType; + public String getName() { return name; @@ -88,6 +93,14 @@ public class RuoYiConfig RuoYiConfig.captchaType = captchaType; } + public static String getFileServer() { + return fileServer; + } + + public void setFileServer(String fileServer) { + RuoYiConfig.fileServer = fileServer; + } + /** * 获取导入上传路径 */ diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/DiskFileUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/DiskFileUtil.java new file mode 100644 index 0000000..43df3b7 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/DiskFileUtil.java @@ -0,0 +1,104 @@ +package com.ruoyi.common.utils.file; + +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.exception.file.FileNameLengthLimitExceededException; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.uuid.UUID; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import java.io.*; +import java.nio.file.Paths; +import java.util.Objects; + +import static com.ruoyi.common.utils.file.FileUtils.getAbsoluteFile; +import static com.ruoyi.common.utils.file.FileUtils.getPathFileName; + +/** + * 磁盘文件操作实现类 + */ +@Component("file:strategy:disk") +public class DiskFileUtil implements FileUtil { + + private static String defaultBaseDir = RuoYiConfig.getProfile(); + + public static void setDefaultBaseDir(String defaultBaseDir) { + DiskFileUtil.defaultBaseDir = defaultBaseDir; + } + + public static String getDefaultBaseDir() { + return defaultBaseDir; + } + + @Override + public String upload(String filePath, MultipartFile file) throws Exception { + int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length(); + if (fileNamelength > FileUtils.DEFAULT_FILE_NAME_LENGTH) { + throw new FileNameLengthLimitExceededException(FileUtils.DEFAULT_FILE_NAME_LENGTH); + } + + // String fileName = extractFilename(file); + + String absPath = getAbsoluteFile(filePath).getAbsolutePath(); + file.transferTo(Paths.get(absPath)); + return getPathFileName(filePath); + } + + @Override + public String upload(MultipartFile file, String name) throws Exception { + try { + return upload(getDefaultBaseDir(), file); + } catch (Exception e) { + throw new IOException(e.getMessage(), e); + } + } + + @Override + public String upload(MultipartFile file) throws Exception { + try { + String filePath = getDefaultBaseDir() + File.separator + DateUtils.dateTime() + File.separator + + DateUtils.dateTimeNow() + UUID.fastUUID().toString().substring(0, 6) + + "." + FileUtils.getExtension(file); + return upload(filePath, file); + } catch (Exception e) { + throw new IOException(e.getMessage(), e); + } + } + + @Override + public String upload(String baseDir, String fileName, MultipartFile file) throws Exception { + String filePath = RuoYiConfig.getProfile() + File.separator + baseDir + File.separator + fileName; + return upload(filePath, file); + } + + @Override + public InputStream downLoad(String filePath) throws Exception { + // 本地资源路径 + String localPath = RuoYiConfig.getProfile(); + // 数据库资源地址 + String downloadPath = localPath + StringUtils.substringAfter(filePath, Constants.RESOURCE_PREFIX); + // 下载名称 + + File file = new File(downloadPath); + if (!file.exists()) { + throw new FileNotFoundException("未找到文件"); + } + return new FileInputStream(file); + } + + @Override + public boolean deleteFile(String filePath) throws Exception { + String relivatePath = StringUtils.substringAfter(filePath, Constants.RESOURCE_PREFIX); + String fileAbs = RuoYiConfig.getProfile() + relivatePath; + boolean flag = false; + File file = new File(fileAbs); + // 路径为文件且不为空则进行删除 + if (file.isFile() && file.exists()) { + flag = file.delete(); + } + return flag; + } + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileOperateUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileOperateUtils.java new file mode 100644 index 0000000..0d1b410 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileOperateUtils.java @@ -0,0 +1,103 @@ +package com.ruoyi.common.utils.file; + +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.utils.spring.SpringUtils; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * 文件上传工具类 + * + * @author ruoyi + */ +public class FileOperateUtils { + + private static FileUtil fileUtil = SpringUtils.getBean("file:strategy:" + RuoYiConfig.getFileServer()); + /** + * 默认大小 50M + */ + public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024; + + /** + * 默认上传的地址 + */ + + /** + * 以默认配置进行文件上传 + * + * @param file 上传的文件 + * @return 文件路径 + * @throws Exception + */ + public static final String upload(MultipartFile file) throws IOException { + try { + FileUtils.assertAllowed(file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION); + return fileUtil.upload(file); + } catch (Exception e) { + throw new IOException(e.getMessage(), e); + } + } + + /** + * 根据文件路径上传 + * + * @param filePath 上传文件的路径 + * @param file 上传的文件 + * @param allowedExtension 允许的扩展名 + * @return 文件名称 + * @throws IOException + */ + public static final String upload(String filePath, MultipartFile file, String[] allowedExtension) throws Exception { + FileUtils.assertAllowed(file, allowedExtension); + return fileUtil.upload(filePath, file); + } + + /** + * 根据文件路径上传 + * + * @param baseDir 相对应用的基目录 + * @param file 上传的文件 + * @param fileName 上传文件名 + * @param allowedExtension 允许的扩展名 + * @return 文件名称 + * @throws IOException + */ + public static final String upload(String baseDir, String fileName, MultipartFile file, + String[] allowedExtension) + throws IOException { + try { + String filePath = baseDir + File.separator + fileName; + return upload(filePath, file, allowedExtension); + } catch (Exception e) { + throw new IOException(e.getMessage(), e); + } + } + + /** + * 根据文件路径下载 + * + * @param fileUrl 下载文件路径 + * @param outputStream 需要输出到的输出流 + * @return 文件名称 + * @throws IOException + */ + public static final void downLoad(String fileUrl, OutputStream outputStream) throws Exception { + InputStream inputStream = fileUtil.downLoad(fileUrl); + FileUtils.writeBytes(inputStream, outputStream); + } + + /** + * 根据文件路径删除 + * + * @param fileUrl 下载文件路径 + * @return 是否成功 + * @throws IOException + */ + public static final boolean deleteFile(String fileUrl) throws Exception { + return fileUtil.deleteFile(fileUrl); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java index 68130b9..3e77f6d 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java @@ -1,8 +1,9 @@ package com.ruoyi.common.utils.file; -import java.io.File; import org.apache.commons.lang3.StringUtils; +import java.io.File; + /** * 文件类型工具类 * @@ -14,7 +15,7 @@ public class FileTypeUtils * 获取文件类型 *

* 例如: ruoyi.txt, 返回: txt - * + * * @param file 文件名 * @return 后缀(不含".") */ @@ -47,7 +48,7 @@ public class FileTypeUtils /** * 获取文件类型 - * + * * @param photoByte 文件字节码 * @return 后缀(不含".") */ @@ -73,4 +74,4 @@ public class FileTypeUtils } return strFileExtendName; } -} \ No newline at end of file +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java deleted file mode 100644 index d9f2b13..0000000 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java +++ /dev/null @@ -1,232 +0,0 @@ -package com.ruoyi.common.utils.file; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Paths; -import java.util.Objects; -import org.apache.commons.io.FilenameUtils; -import org.springframework.web.multipart.MultipartFile; -import com.ruoyi.common.config.RuoYiConfig; -import com.ruoyi.common.constant.Constants; -import com.ruoyi.common.exception.file.FileNameLengthLimitExceededException; -import com.ruoyi.common.exception.file.FileSizeLimitExceededException; -import com.ruoyi.common.exception.file.InvalidExtensionException; -import com.ruoyi.common.utils.DateUtils; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.uuid.Seq; - -/** - * 文件上传工具类 - * - * @author ruoyi - */ -public class FileUploadUtils -{ - /** - * 默认大小 50M - */ - public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024; - - /** - * 默认的文件名最大长度 100 - */ - public static final int DEFAULT_FILE_NAME_LENGTH = 100; - - /** - * 默认上传的地址 - */ - private static String defaultBaseDir = RuoYiConfig.getProfile(); - - public static void setDefaultBaseDir(String defaultBaseDir) - { - FileUploadUtils.defaultBaseDir = defaultBaseDir; - } - - public static String getDefaultBaseDir() - { - return defaultBaseDir; - } - - /** - * 以默认配置进行文件上传 - * - * @param file 上传的文件 - * @return 文件名称 - * @throws Exception - */ - public static final String upload(MultipartFile file) throws IOException - { - try - { - return upload(getDefaultBaseDir(), file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION); - } - catch (Exception e) - { - throw new IOException(e.getMessage(), e); - } - } - - /** - * 根据文件路径上传 - * - * @param baseDir 相对应用的基目录 - * @param file 上传的文件 - * @return 文件名称 - * @throws IOException - */ - public static final String upload(String baseDir, MultipartFile file) throws IOException - { - try - { - return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION); - } - catch (Exception e) - { - throw new IOException(e.getMessage(), e); - } - } - - /** - * 文件上传 - * - * @param baseDir 相对应用的基目录 - * @param file 上传的文件 - * @param allowedExtension 上传文件类型 - * @return 返回上传成功的文件名 - * @throws FileSizeLimitExceededException 如果超出最大大小 - * @throws FileNameLengthLimitExceededException 文件名太长 - * @throws IOException 比如读写文件出错时 - * @throws InvalidExtensionException 文件校验异常 - */ - public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension) - throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException, - InvalidExtensionException - { - int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length(); - if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) - { - throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH); - } - - assertAllowed(file, allowedExtension); - - String fileName = extractFilename(file); - - String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath(); - file.transferTo(Paths.get(absPath)); - return getPathFileName(baseDir, fileName); - } - - /** - * 编码文件名 - */ - public static final String extractFilename(MultipartFile file) - { - return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(), - FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), getExtension(file)); - } - - public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException - { - File desc = new File(uploadDir + File.separator + fileName); - - if (!desc.exists()) - { - if (!desc.getParentFile().exists()) - { - desc.getParentFile().mkdirs(); - } - } - return desc; - } - - public static final String getPathFileName(String uploadDir, String fileName) throws IOException - { - int dirLastIndex = RuoYiConfig.getProfile().length() + 1; - String currentDir = StringUtils.substring(uploadDir, dirLastIndex); - return Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName; - } - - /** - * 文件大小校验 - * - * @param file 上传的文件 - * @return - * @throws FileSizeLimitExceededException 如果超出最大大小 - * @throws InvalidExtensionException - */ - public static final void assertAllowed(MultipartFile file, String[] allowedExtension) - throws FileSizeLimitExceededException, InvalidExtensionException - { - long size = file.getSize(); - if (size > DEFAULT_MAX_SIZE) - { - throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024); - } - - String fileName = file.getOriginalFilename(); - String extension = getExtension(file); - if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension)) - { - if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION) - { - throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension, - fileName); - } - else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION) - { - throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension, - fileName); - } - else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION) - { - throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension, - fileName); - } - else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION) - { - throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension, - fileName); - } - else - { - throw new InvalidExtensionException(allowedExtension, extension, fileName); - } - } - } - - /** - * 判断MIME类型是否是允许的MIME类型 - * - * @param extension - * @param allowedExtension - * @return - */ - public static final boolean isAllowedExtension(String extension, String[] allowedExtension) - { - for (String str : allowedExtension) - { - if (str.equalsIgnoreCase(extension)) - { - return true; - } - } - return false; - } - - /** - * 获取文件名的后缀 - * - * @param file 表单文件 - * @return 后缀名 - */ - public static final String getExtension(MultipartFile file) - { - String extension = FilenameUtils.getExtension(file.getOriginalFilename()); - if (StringUtils.isEmpty(extension)) - { - extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType())); - } - return extension; - } -} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtil.java new file mode 100644 index 0000000..51b8d16 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtil.java @@ -0,0 +1,77 @@ +package com.ruoyi.common.utils.file; + +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.io.InputStream; + +//默认上传下载 +/** + * 文件操作接口 + */ +public interface FileUtil { + + /** + * 文件上传 + * + * @param filePath 上传的文件路径 + * @param file 文件对象 + * @return 返回上传成功的文路径 + * @throws IOException 比如读写文件出错时 + * + */ + public String upload(String filePath, MultipartFile file) throws Exception; + + /** + * 文件上传 + * + * @param filePath 上传的文件路径 + * @param file 文件对象 + * @return 返回上传成功的文路径 + * @throws IOException 比如读写文件出错时 + * + */ + public String upload(MultipartFile file, String name) throws Exception; + + /** + * 文件上传 + * + * @param file 文件对象 + * @return 返回上传成功的文路径 + * @throws IOException 比如读写文件出错时 + * + */ + public String upload(MultipartFile file) throws Exception; + + /** + * 文件上传 + * + * @param baseDir 上传的文件基路径 + * @param fileName 文件名称 + * @param file 文件对象 + * @return 返回上传成功的文路径 + * @throws IOException 比如读写文件出错时 + * + */ + public String upload(String baseDir, String fileName, MultipartFile file) throws Exception; + + /** + * 文件下载 + * + * @param filePath 下载的文件路径 + * @return 返回上传成功的文路径 + * @throws IOException 比如读写文件出错时 + * + */ + public InputStream downLoad(String filePath) throws Exception; + + /** + * 文件下载 + * + * @param filePath 删除的文件路径 + * @return 返回上传成功的文路径 + * @throws IOException 比如读写文件出错时 + * + */ + public boolean deleteFile(String filePath) throws Exception; +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java index 2062b75..70816ed 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java @@ -1,66 +1,63 @@ package com.ruoyi.common.utils.file; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.ArrayUtils; import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.exception.file.FileSizeLimitExceededException; +import com.ruoyi.common.exception.file.InvalidExtensionException; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.uuid.IdUtils; +import com.ruoyi.common.utils.uuid.Seq; +import com.ruoyi.common.utils.uuid.UUID; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.io.FilenameUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.ArrayUtils; +import org.springframework.web.multipart.MultipartFile; + +import java.io.*; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Objects; + +import static com.ruoyi.common.utils.file.FileOperateUtils.DEFAULT_MAX_SIZE; /** * 文件处理工具类 - * + * * @author ruoyi */ -public class FileUtils -{ +public class FileUtils { public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+"; + /** + * 默认的文件名最大长度 100 + */ + public static final int DEFAULT_FILE_NAME_LENGTH = 100; + /** * 输出指定文件的byte数组 - * - * @param filePath 文件路径 + * * @param os 输出流 * @return */ - public static void writeBytes(String filePath, OutputStream os) throws IOException - { - FileInputStream fis = null; - try - { - File file = new File(filePath); - if (!file.exists()) - { - throw new FileNotFoundException(filePath); - } - fis = new FileInputStream(file); + public static void writeBytes(InputStream inputStream, OutputStream os) throws IOException { + + try { + byte[] b = new byte[1024]; int length; - while ((length = fis.read(b)) > 0) - { + while ((length = inputStream.read(b)) > 0) { os.write(b, 0, length); } - } - catch (IOException e) - { + } catch (IOException e) { throw e; - } - finally - { + } finally { IOUtils.close(os); - IOUtils.close(fis); + IOUtils.close(inputStream); } } @@ -71,51 +68,44 @@ public class FileUtils * @return 目标文件 * @throws IOException IO异常 */ - public static String writeImportBytes(byte[] data) throws IOException - { + public static String writeImportBytes(byte[] data) throws IOException { return writeBytes(data, RuoYiConfig.getImportPath()); } /** * 写数据到文件中 * - * @param data 数据 + * @param data 数据 * @param uploadDir 目标文件 * @return 目标文件 * @throws IOException IO异常 */ - public static String writeBytes(byte[] data, String uploadDir) throws IOException - { + public static String writeBytes(byte[] data, String uploadDir) throws IOException { FileOutputStream fos = null; String pathName = ""; - try - { + try { String extension = getFileExtendName(data); pathName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension; - File file = FileUploadUtils.getAbsoluteFile(uploadDir, pathName); + File file = FileUtils.getAbsoluteFile(uploadDir, pathName); fos = new FileOutputStream(file); fos.write(data); - } - finally - { + } finally { IOUtils.close(fos); } - return FileUploadUtils.getPathFileName(uploadDir, pathName); + return FileUtils.getPathFileName(uploadDir, pathName); } /** * 删除文件 - * + * * @param filePath 文件 * @return */ - public static boolean deleteFile(String filePath) - { + public static boolean deleteFile(String filePath) { boolean flag = false; File file = new File(filePath); // 路径为文件且不为空则进行删除 - if (file.isFile() && file.exists()) - { + if (file.isFile() && file.exists()) { flag = file.delete(); } return flag; @@ -123,32 +113,28 @@ public class FileUtils /** * 文件名称验证 - * + * * @param filename 文件名称 * @return true 正常 false 非法 */ - public static boolean isValidFilename(String filename) - { + public static boolean isValidFilename(String filename) { return filename.matches(FILENAME_PATTERN); } /** * 检查文件是否可下载 - * + * * @param resource 需要下载的文件 * @return true 正常 false 非法 */ - public static boolean checkAllowDownload(String resource) - { + public static boolean checkAllowDownload(String resource) { // 禁止目录上跳级别 - if (StringUtils.contains(resource, "..")) - { + if (StringUtils.contains(resource, "..")) { return false; } // 检查允许下载的文件规则 - if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource))) - { + if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource))) { return true; } @@ -158,33 +144,26 @@ public class FileUtils /** * 下载文件名重新编码 - * - * @param request 请求对象 + * + * @param request 请求对象 * @param fileName 文件名 * @return 编码后的文件名 */ - public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException - { + public static String setFileDownloadHeader(HttpServletRequest request, String fileName) + throws UnsupportedEncodingException { final String agent = request.getHeader("USER-AGENT"); String filename = fileName; - if (agent.contains("MSIE")) - { + if (agent.contains("MSIE")) { // IE浏览器 filename = URLEncoder.encode(filename, "utf-8"); filename = filename.replace("+", " "); - } - else if (agent.contains("Firefox")) - { + } else if (agent.contains("Firefox")) { // 火狐浏览器 filename = new String(fileName.getBytes(), "ISO8859-1"); - } - else if (agent.contains("Chrome")) - { + } else if (agent.contains("Chrome")) { // google浏览器 filename = URLEncoder.encode(filename, "utf-8"); - } - else - { + } else { // 其它浏览器 filename = URLEncoder.encode(filename, "utf-8"); } @@ -194,11 +173,11 @@ public class FileUtils /** * 下载文件名重新编码 * - * @param response 响应对象 + * @param response 响应对象 * @param realFileName 真实文件名 */ - public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException - { + public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) + throws UnsupportedEncodingException { String percentEncodedFileName = percentEncode(realFileName); StringBuilder contentDispositionValue = new StringBuilder(); @@ -220,36 +199,27 @@ public class FileUtils * @param s 需要百分号编码的字符串 * @return 百分号编码后的字符串 */ - public static String percentEncode(String s) throws UnsupportedEncodingException - { + public static String percentEncode(String s) throws UnsupportedEncodingException { String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString()); return encode.replaceAll("\\+", "%20"); } /** * 获取图像后缀 - * + * * @param photoByte 图像数据 * @return 后缀名 */ - public static String getFileExtendName(byte[] photoByte) - { + public static String getFileExtendName(byte[] photoByte) { String strFileExtendName = "jpg"; if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56) - && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97)) - { + && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97)) { strFileExtendName = "gif"; - } - else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70)) - { + } else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70)) { strFileExtendName = "jpg"; - } - else if ((photoByte[0] == 66) && (photoByte[1] == 77)) - { + } else if ((photoByte[0] == 66) && (photoByte[1] == 77)) { strFileExtendName = "bmp"; - } - else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71)) - { + } else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71)) { strFileExtendName = "png"; } return strFileExtendName; @@ -257,14 +227,12 @@ public class FileUtils /** * 获取文件名称 /profile/upload/2022/04/16/ruoyi.png -- ruoyi.png - * + * * @param fileName 路径名称 * @return 没有文件路径的名称 */ - public static String getName(String fileName) - { - if (fileName == null) - { + public static String getName(String fileName) { + if (fileName == null) { return null; } int lastUnixPos = fileName.lastIndexOf('/'); @@ -275,17 +243,144 @@ public class FileUtils /** * 获取不带后缀文件名称 /profile/upload/2022/04/16/ruoyi.png -- ruoyi - * + * * @param fileName 路径名称 * @return 没有文件路径和后缀的名称 */ - public static String getNameNotSuffix(String fileName) - { - if (fileName == null) - { + public static String getNameNotSuffix(String fileName) { + if (fileName == null) { return null; } String baseName = FilenameUtils.getBaseName(fileName); return baseName; } + + /** + * 编码文件名 + */ + public static final String extractFilename(MultipartFile file) { + return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(), + FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), + getExtension(file)); + } + + public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException { + File desc = new File(uploadDir + File.separator + fileName); + + if (!desc.exists()) { + if (!desc.getParentFile().exists()) { + desc.getParentFile().mkdirs(); + } + } + return desc; + } + + public static final File getAbsoluteFile(String filePath) throws IOException { + File desc = new File(filePath); + + if (!desc.exists()) { + if (!desc.getParentFile().exists()) { + desc.getParentFile().mkdirs(); + } + } + return desc; + } + + public static final String getPathFileName(String uploadDir, String fileName) throws IOException { + int dirLastIndex = RuoYiConfig.getProfile().length() + 1; + String currentDir = StringUtils.substring(uploadDir, dirLastIndex); + return Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName; + } + + public static final String getPathFileName(String filePath) throws IOException { + int dirLastIndex = RuoYiConfig.getProfile().length() + 1; + String currentDir = StringUtils.substring(filePath, dirLastIndex); + return Constants.RESOURCE_PREFIX + "/" + currentDir; + } + + /** + * 文件大小校验 + * + * @param file 上传的文件 + * @return + * @throws FileSizeLimitExceededException 如果超出最大大小 + * @throws InvalidExtensionException + */ + public static final void assertAllowed(MultipartFile file, String[] allowedExtension) + throws FileSizeLimitExceededException, InvalidExtensionException { + long size = file.getSize(); + if (size > DEFAULT_MAX_SIZE) { + throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024); + } + + String fileName = file.getOriginalFilename(); + String extension = getExtension(file); + if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension)) { + if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION) { + throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension, + fileName); + } else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION) { + throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension, + fileName); + } else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION) { + throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension, + fileName); + } else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION) { + throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension, + fileName); + } else { + throw new InvalidExtensionException(allowedExtension, extension, fileName); + } + } + } + + /** + * 判断MIME类型是否是允许的MIME类型 + * + * @param extension + * @param allowedExtension + * @return + */ + public static final boolean isAllowedExtension(String extension, String[] allowedExtension) { + for (String str : allowedExtension) { + if (str.equalsIgnoreCase(extension)) { + return true; + } + } + return false; + } + + /** + * 获取文件名的后缀 + * + * @param file 表单文件 + * @return 后缀名 + */ + public static final String getExtension(MultipartFile file) { + String extension = FilenameUtils.getExtension(file.getOriginalFilename()); + if (StringUtils.isEmpty(extension)) { + extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType())); + } + return extension; + } + + public static final String getRelativePath(String filePath) { + Path absolute = Paths.get(filePath); + Path root = absolute.getRoot(); + Path normalize = absolute.normalize(); + return normalize.subpath(root.getNameCount(), normalize.getNameCount()).toString().replace("\\", "/"); + } + + public static final boolean isAbsolutePath(String path) { + Path filePath = Paths.get(path); + return filePath.isAbsolute(); + } + + public static final String fastFilePath(MultipartFile file) { + return new StringBuilder(DateUtils.datePath()) + .append(File.separatorChar).append(DateUtils.dateTimeNow()) + .append("_").append(UUID.fastUUID().toString().substring(0, 4)) + .append(".").append(FileUtils.getExtension(file)).toString(); + } + } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java index 432dfda..0ef3317 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java @@ -1,17 +1,18 @@ package com.ruoyi.common.utils.file; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.utils.StringUtils; +import org.apache.poi.util.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.ByteArrayInputStream; import java.io.FileInputStream; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; import java.util.Arrays; -import org.apache.poi.util.IOUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import com.ruoyi.common.config.RuoYiConfig; -import com.ruoyi.common.constant.Constants; -import com.ruoyi.common.utils.StringUtils; /** * 图片处理工具类 @@ -57,7 +58,7 @@ public class ImageUtils /** * 读取文件为字节数据 - * + * * @param url 地址 * @return 字节数据 */ diff --git a/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/config/MinioClientConfig.java b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/config/MinioClientConfig.java new file mode 100644 index 0000000..6a072c3 --- /dev/null +++ b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/config/MinioClientConfig.java @@ -0,0 +1,103 @@ +package com.ruoyi.middleware.minio.config; + +import io.minio.MinioClient; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +@Component +@ConfigurationProperties("minio.client") +public class MinioClientConfig { + + public MinioClientEntity getMaster() { + return master; + } + + public void setMaster(MinioClientEntity master) { + this.master = master; + } + + public List getSlave() { + return slave; + } + + public void setSlave(List slave) { + this.slave = slave; + } + + private MinioClientEntity master; + + private List slave = new ArrayList<>(); + + public static class MinioClientEntity { + + private String url; + private String accessKey; + private String secretKey; + private String name; + private String defaultBuket; + + private MinioClient client; + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + 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 getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDefaultBuket() { + return defaultBuket; + } + + public void setDefaultBuket(String defaultBuket) { + this.defaultBuket = defaultBuket; + } + + public MinioClient getClient() { + return client; + } + + public void setClient(MinioClient client) { + this.client = client; + } + + public MinioClientEntity(String url, String accessKey, String secretKey, String name, String defaultBuket) { + this.url = url; + this.accessKey = accessKey; + this.secretKey = secretKey; + this.name = name; + this.defaultBuket=defaultBuket; + } + + public MinioClientEntity() { + } + } +} diff --git a/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/config/MinioConfig.java b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/config/MinioConfig.java index d339c05..d0669d5 100644 --- a/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/config/MinioConfig.java +++ b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/config/MinioConfig.java @@ -1,80 +1,68 @@ package com.ruoyi.middleware.minio.config; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import io.minio.MinioClient; +import jakarta.annotation.PostConstruct; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Configuration; -/** - * Minio 配置信息 - * - * @author ruoyi - */ -@Configuration -@ConfigurationProperties(prefix = "minio") +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; + +@Configuration("MinioConfiguration") +@ConditionalOnProperty(prefix = "minio",name = {"enable"},havingValue = "true" , matchIfMissing = false) public class MinioConfig { - /** - * 服务地址 - */ - private static String url; + public int maxSize; - /** - * 用户名 - */ - private static String accessKey; + public static String prefix="/minio"; + @Autowired + private MinioClientConfig minioClientConfig; - /** - * 密码 - */ - private static String secretKey; + private Map slaveClients = new ConcurrentHashMap<>(); - /** - * 存储桶名称 - */ - private static String bucketName; + private List slaveClientsList = new CopyOnWriteArrayList<>(); - public static String getUrl() { - return url; - } + private MinioClientConfig.MinioClientEntity masterClient; - public void setUrl(String url) { - MinioConfig.url = url; - } + @PostConstruct + public void init() { + System.out.println(maxSize); + List collect = minioClientConfig.getSlave().stream().map(item -> { + item.setClient(MinioClient.builder().endpoint(item.getUrl()).credentials(item.getAccessKey(), item.getSecretKey()).build()); + return item; + }).toList(); + collect.forEach(item->{ + slaveClients.put(item.getName(),item); + slaveClientsList.add(item); + }); - public static String getAccessKey() { - return accessKey; + MinioClientConfig.MinioClientEntity master = minioClientConfig.getMaster(); + master.setClient(MinioClient.builder().credentials(master.getAccessKey(),master.getSecretKey()).endpoint(master.getUrl()).build()); + masterClient = master; } - public void setAccessKey(String accessKey) { - MinioConfig.accessKey = accessKey; + public int getMaxSize() { + return maxSize; } - public static String getSecretKey() { - return secretKey; + private void setMaxSize(int maxSize) { + this.maxSize = maxSize; } - public void setSecretKey(String secretKey) { - MinioConfig.secretKey = secretKey; + public List getSlaveClientsList() { + return slaveClientsList; } - public static String getBucketName() { - return bucketName; + public Map getSlaveClients() { + return this.slaveClients; } - public void setBucketName(String bucketName) { - MinioConfig.bucketName = bucketName; + public MinioClientConfig.MinioClientEntity getMasterClient() { + return this.masterClient; } - @Bean - public MinioClient getMinioClient() { - try { - return MinioClient.builder().endpoint(url).credentials(accessKey, secretKey).build(); - } catch (Exception e) { - - return null; - } - - } } diff --git a/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/controller/MinioController.java b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/controller/MinioController.java index 48159c8..45858cd 100644 --- a/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/controller/MinioController.java +++ b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/controller/MinioController.java @@ -1,32 +1,44 @@ package com.ruoyi.middleware.minio.controller; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.multipart.MultipartFile; - import com.ruoyi.common.annotation.Anonymous; import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.file.FileUtils; -import com.ruoyi.middleware.minio.utils.FileUploadMinioUtils; +import com.ruoyi.middleware.minio.domain.MinioFileVO; + +import com.ruoyi.middleware.minio.utils.MinioUtil; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import okhttp3.Headers; +import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/minio") public class MinioController { - @PostMapping("/upload") + + + @GetMapping("/{buketName}") @Anonymous - public AjaxResult uploadFileMinio(MultipartFile file) throws Exception { - try { - // 上传并返回新文件名称 - String fileName = FileUploadMinioUtils.uploadMinio(file); - AjaxResult ajax = AjaxResult.success(); - ajax.put("url", fileName); - ajax.put("fileName", fileName); - ajax.put("newFileName", FileUtils.getName(fileName)); - ajax.put("originalFilename", file.getOriginalFilename()); - return ajax; - } catch (Exception e) { - return AjaxResult.error(e.getMessage()); + public void downLoadFile(HttpServletRequest request, HttpServletResponse response, + @PathVariable("buketName") String buketName, + @RequestParam("fileName") String fileName, + @RequestParam(value = "clientName", required = false) String clientName) throws Exception { + + if (!StringUtils.isEmpty(clientName)) { + MinioFileVO file = MinioUtil.SlaveClient.getFile(clientName, buketName, fileName); + Headers headers = file.getHeaders(); + + String contentType = headers.get("content-Type"); + response.setContentType(contentType); + FileUtils.writeBytes(file.getFileInputSteam(), response.getOutputStream()); + } else { + MinioFileVO file = MinioUtil.getFile(buketName, fileName); + + Headers headers = file.getHeaders(); + String contentType = headers.get("content-Type"); + response.setContentType(contentType); + FileUtils.writeBytes(file.getFileInputSteam(), response.getOutputStream()); } } } diff --git a/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/domain/MinioFileVO.java b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/domain/MinioFileVO.java new file mode 100644 index 0000000..a2f433f --- /dev/null +++ b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/domain/MinioFileVO.java @@ -0,0 +1,68 @@ +package com.ruoyi.middleware.minio.domain; + + +import okhttp3.Headers; + +import java.io.InputStream; + +public class MinioFileVO { + + + private InputStream fileInputSteam; + private String object; + private Headers headers; + private String buket; + private String region; + public InputStream getFileInputSteam() { + return fileInputSteam; + } + + public void setFileInputSteam(InputStream fileInputSteam) { + this.fileInputSteam = fileInputSteam; + } + + + public String getObject() { + return object; + } + + public void setObject(String object) { + this.object = object; + } + + public Headers getHeaders() { + return headers; + } + + public void setHeaders(Headers headers) { + this.headers = headers; + } + + public String getBuket() { + return buket; + } + + public void setBuket(String buket) { + this.buket = buket; + } + + public String getRegion() { + return region; + } + + public void setRegion(String region) { + this.region = region; + } + + public MinioFileVO(InputStream fileInputSteam, String object, Headers headers, String buket, String region) { + this.fileInputSteam = fileInputSteam; + this.object = object; + this.headers = headers; + this.buket = buket; + this.region = region; + } + + public MinioFileVO() { + } + +} diff --git a/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/exception/MinioClientErrorException.java b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/exception/MinioClientErrorException.java new file mode 100644 index 0000000..35dfde3 --- /dev/null +++ b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/exception/MinioClientErrorException.java @@ -0,0 +1,7 @@ +package com.ruoyi.middleware.minio.exception; + +public class MinioClientErrorException extends RuntimeException{ + public MinioClientErrorException(String msg){ + super(msg); + } +} diff --git a/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/exception/MinioClientNotFundException.java b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/exception/MinioClientNotFundException.java new file mode 100644 index 0000000..02b4d27 --- /dev/null +++ b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/exception/MinioClientNotFundException.java @@ -0,0 +1,4 @@ +package com.ruoyi.middleware.minio.exception; + +public class MinioClientNotFundException extends RuntimeException{ +} diff --git a/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/utils/FileUploadMinioUtils.java b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/utils/FileUploadMinioUtils.java deleted file mode 100644 index 07530af..0000000 --- a/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/utils/FileUploadMinioUtils.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.ruoyi.middleware.minio.utils; - -import java.io.IOException; - -import org.springframework.web.multipart.MultipartFile; - -import com.ruoyi.common.exception.file.FileNameLengthLimitExceededException; -import com.ruoyi.common.exception.file.FileSizeLimitExceededException; -import com.ruoyi.common.exception.file.InvalidExtensionException; -import com.ruoyi.common.utils.file.FileUploadUtils; -import com.ruoyi.common.utils.file.MimeTypeUtils; -import com.ruoyi.middleware.minio.config.MinioConfig; - -public class FileUploadMinioUtils extends FileUploadUtils { - /** - * Minio默认上传的地址 - */ - private static String bucketName = MinioConfig.getBucketName(); - - public static String getBucketName() - { - return bucketName; - } - - /** - * 以默认BucketName配置上传到Minio服务器 - * - * @param file 上传的文件 - * @return 文件名称 - * @throws Exception - */ - public static final String uploadMinio(MultipartFile file) throws IOException - { - try - { - return uploadMinino(getBucketName(), file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION); - } - catch (Exception e) - { - throw new IOException(e.getMessage(), e); - } - } - - /** - * 自定义bucketName配置上传到Minio服务器 - * - * @param file 上传的文件 - * @return 文件名称 - * @throws Exception - */ - public static final String uploadMinio(MultipartFile file, String bucketName) throws IOException - { - try - { - return uploadMinino(bucketName, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION); - } - catch (Exception e) - { - throw new IOException(e.getMessage(), e); - } - } - - private static final String uploadMinino(String bucketName, MultipartFile file, String[] allowedExtension) - throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException, - InvalidExtensionException - { - int fileNamelength = file.getOriginalFilename().length(); - if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) - { - throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH); - } - assertAllowed(file, allowedExtension); - try - { - String fileName = extractFilename(file); - String pathFileName = MinioUtil.uploadFile(bucketName, fileName, file); - return pathFileName; - } - catch (Exception e) - { - throw new IOException(e.getMessage(), e); - } - } -} diff --git a/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/utils/MinioFileUtil.java b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/utils/MinioFileUtil.java new file mode 100644 index 0000000..2cc4add --- /dev/null +++ b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/utils/MinioFileUtil.java @@ -0,0 +1,66 @@ +package com.ruoyi.middleware.minio.utils; + +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.file.FileUtil; +import com.ruoyi.common.utils.file.FileUtils; +import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.middleware.minio.config.MinioConfig; +import com.ruoyi.middleware.minio.domain.MinioFileVO; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.InputStream; + +/** + * Minio文件操作实现类 + */ +@Component("file:strategy:minio") +public class MinioFileUtil implements FileUtil { + private static MinioConfig minioConfig = SpringUtils.getBean(MinioConfig.class); + + @Override + public String upload(String filePath, MultipartFile file) throws Exception { + String relativePath = null; + if (FileUtils.isAbsolutePath(filePath)) { + relativePath = FileUtils.getRelativePath(filePath); + } else { + String absPath = RuoYiConfig.getProfile() + File.separator + filePath; + relativePath = FileUtils.getRelativePath(absPath); + } + return MinioUtil.uploadFile(minioConfig.getMasterClient().getDefaultBuket(), relativePath, file); + } + + @Override + public String upload(MultipartFile file, String name) throws Exception { + return MinioUtil.uploadFile(minioConfig.getMasterClient().getDefaultBuket(), name, file); + } + + @Override + public String upload(MultipartFile file) throws Exception { + String filePath = RuoYiConfig.getProfile() + File.separator + FileUtils.fastFilePath(file); + return upload(filePath, file); + } + + @Override + public String upload(String baseDir, String fileName, MultipartFile file) throws Exception { + + return upload(baseDir + File.pathSeparator + fileName, file); + } + + @Override + public InputStream downLoad(String fileUrl) throws Exception { + String filePath = StringUtils.substringAfter(fileUrl, "?filePath="); + MinioFileVO file = MinioUtil.getFile(minioConfig.getMasterClient().getDefaultBuket(), filePath); + return file.getFileInputSteam(); + } + + @Override + public boolean deleteFile(String fileUrl) throws Exception { + String filePath = StringUtils.substringAfter(fileUrl, "?filePath="); + MinioUtil.removeFile(minioConfig.getMasterClient().getDefaultBuket(), filePath); + return true; + } +} diff --git a/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/utils/MinioUtil.java b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/utils/MinioUtil.java index 46783c0..6f5157a 100644 --- a/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/utils/MinioUtil.java +++ b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/utils/MinioUtil.java @@ -1,46 +1,277 @@ package com.ruoyi.middleware.minio.utils; -import java.io.IOException; -import java.io.InputStream; - -import org.springframework.web.multipart.MultipartFile; - -import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.exception.file.FileException; +import com.ruoyi.common.exception.file.FileNameLengthLimitExceededException; +import com.ruoyi.common.exception.file.FileSizeLimitExceededException; +import com.ruoyi.common.exception.file.InvalidExtensionException; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.file.FileUtils; import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.common.utils.uuid.UUID; +import com.ruoyi.middleware.minio.config.MinioClientConfig; +import com.ruoyi.middleware.minio.config.MinioConfig; +import com.ruoyi.middleware.minio.domain.MinioFileVO; +import com.ruoyi.middleware.minio.exception.MinioClientErrorException; +import com.ruoyi.middleware.minio.exception.MinioClientNotFundException; +import io.minio.*; +import io.minio.messages.DeleteError; +import org.springframework.web.multipart.MultipartFile; -import io.minio.GetPresignedObjectUrlArgs; -import io.minio.MinioClient; -import io.minio.PutObjectArgs; -import io.minio.http.Method; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; /** - * Minio 文件存储工具类 + * Minio工具 * - * @author ruoyi */ -public class MinioUtil -{ +public class MinioUtil { + + private static MinioConfig minioConfig = SpringUtils.getBean(MinioConfig.class); + /** - * 上传文件 + * 文件上传 + * + * @param buketName Minio的桶名 + * @param filePath 上传的文件路径 + * @param contentType 上传文件类型 + * @param inputStream 上传文件的输入流 + * @return 返回上传成功的文路径 + * @throws IOException 比如读写文件出错时 * - * @param bucketName 桶名称 - * @param fileName - * @throws IOException - */ - public static String uploadFile(String bucketName, String fileName, MultipartFile multipartFile) throws IOException - { - String url = ""; - MinioClient minioClient = SpringUtils.getBean(MinioClient.class); - try (InputStream inputStream = multipartFile.getInputStream()) - { - minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(inputStream, multipartFile.getSize(), -1).contentType(multipartFile.getContentType()).build()); - url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(fileName).method(Method.GET).build()); - url = url.substring(0, url.indexOf('?')); - return ServletUtils.urlDecode(url); - } - catch (Exception e) - { - throw new IOException(e.getMessage(), e); + */ + public static String uploadFile(String buketName, String filePath, + String contentType, InputStream inputStream) + throws Exception { + PutObjectArgs build = PutObjectArgs.builder().contentType(contentType) + .stream(inputStream, inputStream.available(), -1) + .bucket(buketName).object(filePath).build(); + return uploadFile(build); + } + + /** + * 文件上传 + * + * @param putObjectArgs Minio上传参数 + * @return 返回上传成功的文件路径 + */ + public static String uploadFile(PutObjectArgs putObjectArgs) throws Exception { + try { + MinioClientConfig.MinioClientEntity masterClient = minioConfig.getMasterClient(); + masterClient.getClient().putObject(putObjectArgs); + StringBuilder url = new StringBuilder(); + url.append(MinioConfig.prefix).append("/").append(masterClient.getDefaultBuket()) + // .append("/").append(filePath) + .append("?").append("fileName=").append(putObjectArgs.object()); + return url.toString(); + } catch (Exception e) { + throw new MinioClientErrorException(e.getMessage()); + } + + } + + /** + * 文件上传(从节点递归,直到上传成功) + * + * @param index 开始递归的从节点索引 + * @param putObjectArgs Minio上传文件参数 + * @return 返回上传成功的文件路径 + */ + private static String uploadFileIterator(int index, PutObjectArgs putObjectArgs) { + List slaveClientsList = minioConfig.getSlaveClientsList(); + if (index >= slaveClientsList.size()) { + throw new MinioClientNotFundException(); + } + try { + MinioClientConfig.MinioClientEntity minioClientEntity = slaveClientsList.get(index); + PutObjectArgs build = PutObjectArgs.builder().contentType(putObjectArgs.contentType()) + .object(putObjectArgs.object()) + .stream(putObjectArgs.stream(), putObjectArgs.stream().available(), -1) + .bucket(minioClientEntity.getDefaultBuket()).build(); + minioClientEntity.getClient().putObject(build); + StringBuilder url = new StringBuilder(); + url.append(MinioConfig.prefix).append("/").append(minioClientEntity.getDefaultBuket()) + .append("?").append("fileName=").append(putObjectArgs.object()) + .append("&").append("clientName=").append(minioClientEntity.getName()); + return url.toString(); + } catch (Exception e) { + return uploadFileIterator(index + 1, putObjectArgs); + } + } + + /** + * 文件上传 + * + * @param buketName Minio的桶名 + * @param file 上传的文件 + * @param fileName 上传文件名 + * @return 返回上传成功的文件名 + * @throws IOException 比如读写文件出错时 + */ + public static String uploadFile(String buketName, String fileName, MultipartFile file) throws Exception { + return uploadFile(buketName, fileName, file.getContentType(), file.getInputStream()); + } + + /** + * 文件上传 + * + * @param buketName Minio的桶名 + * @param file 上传的文件 + * @return 返回上传成功的文件名 + * @throws IOException 比如读写文件出错时 + */ + public static String uploadFile(String buketName, MultipartFile file) throws Exception { + String fileName = DateUtils.dateTimeNow() + UUID.fastUUID().toString().substring(0, 5) + "." + + FileUtils.getExtension(file); + + return uploadFile(buketName, fileName, file.getContentType(), file.getInputStream()); + } + + /** + * 文件删除 + * + * @param removeObjectArgs Minio删除文件的参数对象 + * @throws IOException 比如读写文件出错时 + */ + public static void removeFile(RemoveObjectArgs removeObjectArgs) throws Exception { + minioConfig.getMasterClient().getClient().removeObject(removeObjectArgs); + } + + /** + * 文件删除 + * + * @param buketName Minio的桶名 + * @param filePath 上传文件路径 + * @throws IOException 比如读写文件出错时 + */ + public static void removeFile(String buketName, String filePath) throws Exception { + RemoveObjectArgs build = RemoveObjectArgs.builder().object(filePath).bucket(buketName).build(); + removeFile(build); + } + + /** + * 文件批量删除 + * + * @param removeObjectsArgs Minio批量删除文件参数对象 + * @return 删除结果 + * @throws IOException 比如读写文件出错时 + */ + public static Iterable> removeFiles(RemoveObjectsArgs removeObjectsArgs) { + return minioConfig.getMasterClient().getClient().removeObjects(removeObjectsArgs); + } + + /** + * 文件下载 + * + * @param getObjectArgs Minio获取文件参数对象 + * @return 返回封装的Minio下载结果对象 + * @throws IOException 比如读写文件出错时 + */ + public static MinioFileVO getFile(GetObjectArgs getObjectArgs) throws Exception { + GetObjectResponse inputStream = minioConfig.getMasterClient().getClient().getObject(getObjectArgs); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + byte[] bytes = new byte[minioConfig.maxSize]; + int length = 0; + while (true) { + try { + if (!((length = inputStream.read(bytes, 0, bytes.length)) > 0)) { + break; + } + } catch (Exception e) { + throw new FileException("500", new String[] { e.getMessage() }); + } + byteArrayOutputStream.write(bytes, 0, length); + } + return new MinioFileVO(inputStream, inputStream.object(), inputStream.headers(), inputStream.bucket(), + inputStream.region()); + } + + /** + * 文件下载 + * + * @param buketName Minio的桶名 + * @param filePath 文件路径 + * @return 返回封装的Minio下载文件对象 + * @throws IOException 比如读写文件出错时 + */ + public static MinioFileVO getFile(String buketName, String filePath) throws Exception { + GetObjectArgs build = GetObjectArgs.builder().object(filePath).bucket(buketName).build(); + return getFile(build); + } + + /** + * 从节点对应操作工具类 + */ + public static class SlaveClient { + public static String uploadFile(String clientName, String buketName, String fileName, + String contentType, InputStream inputStream) + throws Exception { + PutObjectArgs build = PutObjectArgs.builder().contentType(contentType) + .stream(inputStream, inputStream.available(), -1) + .bucket(buketName).object(fileName).build(); + return uploadFile(clientName, build); } + + public static String uploadFile(String clientName, PutObjectArgs putObjectArgs) throws Exception { + MinioClientConfig.MinioClientEntity minioClientEntity = minioConfig.getSlaveClients().get(clientName); + minioClientEntity.getClient().putObject(putObjectArgs); + StringBuilder url = new StringBuilder(); + url.append(MinioConfig.prefix).append("/").append(minioClientEntity.getDefaultBuket()) + .append("?").append("fileName=").append(putObjectArgs.object()) + .append("&").append("clientName=").append(minioClientEntity.getName()); + return url.toString(); + } + + public static String uploadFile(String clientName, String buketName, String fileName, MultipartFile file) + throws Exception { + + return uploadFile(clientName, buketName, fileName, file.getContentType(), file.getInputStream()); + } + + public static String uploadFile(String clientName, String buketName, MultipartFile file) throws Exception { + String fileName = DateUtils.dateTimeNow() + UUID.fastUUID().toString().substring(0, 5); + return uploadFile(clientName, buketName, fileName, file.getContentType(), file.getInputStream()); + } + + public static void removeFile(String clientName, RemoveObjectArgs removeObjectArgs) throws Exception { + minioConfig.getSlaveClients().get(clientName).getClient().removeObject(removeObjectArgs); + } + + public static void removeFile(String clientName, String buketName, String fileName) throws Exception { + RemoveObjectArgs build = RemoveObjectArgs.builder().object(fileName).bucket(buketName).build(); + removeFile(clientName, build); + } + + public static Iterable> removeFiles(RemoveObjectsArgs removeObjectsArgs) { + return minioConfig.getMasterClient().getClient().removeObjects(removeObjectsArgs); + } + + public static MinioFileVO getFile(String clientName, GetObjectArgs getObjectArgs) throws Exception { + GetObjectResponse inputStream = minioConfig.getSlaveClients().get(clientName).getClient() + .getObject(getObjectArgs); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + byte[] bytes = new byte[minioConfig.maxSize]; + int length = 0; + while (true) { + try { + if (!((length = inputStream.read(bytes, 0, bytes.length)) > 0)) { + break; + } + } catch (Exception e) { + throw new FileException("500", new String[] { e.getMessage() }); + } + byteArrayOutputStream.write(bytes, 0, length); + } + return new MinioFileVO(inputStream, inputStream.object(), inputStream.headers(), inputStream.bucket(), + inputStream.region()); + } + + public static MinioFileVO getFile(String clientName, String buketName, String fileName) throws Exception { + GetObjectArgs build = GetObjectArgs.builder().object(fileName).bucket(buketName).build(); + return getFile(clientName, build); + } + } + } -- Gitee From 2f681058264ba204ae18fe80e0706179132f8e4e Mon Sep 17 00:00:00 2001 From: XSWL1018 <824576966@qq.com> Date: Mon, 17 Jun 2024 17:08:52 +0800 Subject: [PATCH 2/7] init --- .../java/com/ruoyi/middleware/minio/utils/MinioFileUtil.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/utils/MinioFileUtil.java b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/utils/MinioFileUtil.java index 2cc4add..4773427 100644 --- a/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/utils/MinioFileUtil.java +++ b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/utils/MinioFileUtil.java @@ -52,14 +52,14 @@ public class MinioFileUtil implements FileUtil { @Override public InputStream downLoad(String fileUrl) throws Exception { - String filePath = StringUtils.substringAfter(fileUrl, "?filePath="); + String filePath = StringUtils.substringAfter(fileUrl, "?fileName="); MinioFileVO file = MinioUtil.getFile(minioConfig.getMasterClient().getDefaultBuket(), filePath); return file.getFileInputSteam(); } @Override public boolean deleteFile(String fileUrl) throws Exception { - String filePath = StringUtils.substringAfter(fileUrl, "?filePath="); + String filePath = StringUtils.substringAfter(fileUrl, "?fileName="); MinioUtil.removeFile(minioConfig.getMasterClient().getDefaultBuket(), filePath); return true; } -- Gitee From 586d8048e7334bd952f9e1133ff0c46b7fa94567 Mon Sep 17 00:00:00 2001 From: XSWL1018 <824576966@qq.com> Date: Tue, 18 Jun 2024 11:26:10 +0800 Subject: [PATCH 3/7] up --- .../minio/config/MinioClientConfig.java | 2 +- .../middleware/minio/config/MinioConfig.java | 25 +++++++++++++------ .../middleware/minio/utils/MinioFileUtil.java | 3 +-- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/config/MinioClientConfig.java b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/config/MinioClientConfig.java index 6a072c3..b2491af 100644 --- a/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/config/MinioClientConfig.java +++ b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/config/MinioClientConfig.java @@ -94,7 +94,7 @@ public class MinioClientConfig { this.accessKey = accessKey; this.secretKey = secretKey; this.name = name; - this.defaultBuket=defaultBuket; + this.defaultBuket = defaultBuket; } public MinioClientEntity() { diff --git a/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/config/MinioConfig.java b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/config/MinioConfig.java index d0669d5..af55924 100644 --- a/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/config/MinioConfig.java +++ b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/config/MinioConfig.java @@ -1,6 +1,5 @@ package com.ruoyi.middleware.minio.config; - import io.minio.MinioClient; import jakarta.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; @@ -13,12 +12,12 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; @Configuration("MinioConfiguration") -@ConditionalOnProperty(prefix = "minio",name = {"enable"},havingValue = "true" , matchIfMissing = false) +@ConditionalOnProperty(prefix = "minio", name = { "enable" }, havingValue = "true", matchIfMissing = false) public class MinioConfig { public int maxSize; - public static String prefix="/minio"; + public static String prefix = "/minio"; @Autowired private MinioClientConfig minioClientConfig; @@ -30,18 +29,28 @@ public class MinioConfig { @PostConstruct public void init() { - System.out.println(maxSize); List collect = minioClientConfig.getSlave().stream().map(item -> { - item.setClient(MinioClient.builder().endpoint(item.getUrl()).credentials(item.getAccessKey(), item.getSecretKey()).build()); + try { + item.setClient(MinioClient.builder().endpoint(item.getUrl()) + .credentials(item.getAccessKey(), item.getSecretKey()).build()); + } catch (Exception exception) { + item.setClient(MinioClient.builder().endpoint(item.getUrl()).build()); + } + return item; }).toList(); - collect.forEach(item->{ - slaveClients.put(item.getName(),item); + collect.forEach(item -> { + slaveClients.put(item.getName(), item); slaveClientsList.add(item); }); MinioClientConfig.MinioClientEntity master = minioClientConfig.getMaster(); - master.setClient(MinioClient.builder().credentials(master.getAccessKey(),master.getSecretKey()).endpoint(master.getUrl()).build()); + try { + master.setClient(MinioClient.builder().endpoint(master.getUrl()) + .credentials(master.getAccessKey(), master.getSecretKey()).build()); + } catch (Exception exception) { + master.setClient(MinioClient.builder().endpoint(master.getUrl()).build()); + } masterClient = master; } diff --git a/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/utils/MinioFileUtil.java b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/utils/MinioFileUtil.java index 4773427..7be7e4f 100644 --- a/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/utils/MinioFileUtil.java +++ b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/utils/MinioFileUtil.java @@ -27,8 +27,7 @@ public class MinioFileUtil implements FileUtil { if (FileUtils.isAbsolutePath(filePath)) { relativePath = FileUtils.getRelativePath(filePath); } else { - String absPath = RuoYiConfig.getProfile() + File.separator + filePath; - relativePath = FileUtils.getRelativePath(absPath); + relativePath = filePath; } return MinioUtil.uploadFile(minioConfig.getMasterClient().getDefaultBuket(), relativePath, file); } -- Gitee From 4a5ab6b0d9a9bd50407580d93a8e6c9da9cc7ec5 Mon Sep 17 00:00:00 2001 From: XSWL1018 <824576966@qq.com> Date: Tue, 18 Jun 2024 23:18:00 +0800 Subject: [PATCH 4/7] init --- .../src/main/resources/application-druid.yml | 2 +- .../main/resources/application-middleware.yml | 4 +- .../middleware/minio/config/MinioConfig.java | 63 ++++++++++++++----- 3 files changed, 52 insertions(+), 17 deletions(-) diff --git a/ruoyi-admin/src/main/resources/application-druid.yml b/ruoyi-admin/src/main/resources/application-druid.yml index 56ce492..758c7d6 100644 --- a/ruoyi-admin/src/main/resources/application-druid.yml +++ b/ruoyi-admin/src/main/resources/application-druid.yml @@ -8,7 +8,7 @@ spring: master: url: jdbc:mysql://127.0.0.1/ry?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 username: root - password: 123456 + password: WKY20031018 # 从库数据源 slave: # 从数据源开关/默认关闭 diff --git a/ruoyi-admin/src/main/resources/application-middleware.yml b/ruoyi-admin/src/main/resources/application-middleware.yml index 0b6534d..f0122b7 100644 --- a/ruoyi-admin/src/main/resources/application-middleware.yml +++ b/ruoyi-admin/src/main/resources/application-middleware.yml @@ -31,5 +31,5 @@ minio: master: url: http://localhost:9000 accessKey: root - secretKey: 123456 - defaultBuket: ruoyi + secretKey: wky20031018 + defaultBuket: bim-model diff --git a/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/config/MinioConfig.java b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/config/MinioConfig.java index af55924..012999e 100644 --- a/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/config/MinioConfig.java +++ b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/config/MinioConfig.java @@ -1,11 +1,17 @@ package com.ruoyi.middleware.minio.config; +import com.ruoyi.common.utils.StringUtils; import io.minio.MinioClient; +import io.minio.errors.*; +import io.minio.messages.Bucket; import jakarta.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Configuration; +import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -30,27 +36,17 @@ public class MinioConfig { @PostConstruct public void init() { List collect = minioClientConfig.getSlave().stream().map(item -> { - try { - item.setClient(MinioClient.builder().endpoint(item.getUrl()) - .credentials(item.getAccessKey(), item.getSecretKey()).build()); - } catch (Exception exception) { - item.setClient(MinioClient.builder().endpoint(item.getUrl()).build()); - } - + setClient(item); + isBuketExist(item); return item; }).toList(); collect.forEach(item -> { slaveClients.put(item.getName(), item); slaveClientsList.add(item); }); - MinioClientConfig.MinioClientEntity master = minioClientConfig.getMaster(); - try { - master.setClient(MinioClient.builder().endpoint(master.getUrl()) - .credentials(master.getAccessKey(), master.getSecretKey()).build()); - } catch (Exception exception) { - master.setClient(MinioClient.builder().endpoint(master.getUrl()).build()); - } + setClient(master); + isBuketExist(master); masterClient = master; } @@ -74,4 +70,43 @@ public class MinioConfig { return this.masterClient; } + private static void setClient(MinioClientConfig.MinioClientEntity entity){ + try { + MinioClient build = MinioClient.builder().endpoint(entity.getUrl()) + .credentials(entity.getAccessKey(), entity.getSecretKey()).build(); + build.listBuckets(); + entity.setClient(build); + } catch (Exception exception) { + MinioClient build = MinioClient.builder().endpoint(entity.getUrl()).build(); + try { + build.listBuckets(); + } catch (Exception e) { + throw new RuntimeException(e); + } + entity.setClient(build); + } + } + + private static void isBuketExist(MinioClientConfig.MinioClientEntity entity) { + try { + String defaultBuket = entity.getDefaultBuket(); + if(StringUtils.isEmpty(defaultBuket)){ + throw new RuntimeException("defaultBuket without a default value "); + } + List buckets = entity.getClient().listBuckets(); + if (buckets.isEmpty()) { + throw new RuntimeException("minioClient without any buket"); + } + for (Bucket bucket : buckets) { + if (bucket.name().equals(entity.getDefaultBuket())) { + return; + } + } + throw new RuntimeException("configured defaultBucket does not exist"); + }catch (Exception e){ + throw new RuntimeException(e); + } + + } + } -- Gitee From 8a6f6a055b75a11b03b2f931cd1872a00b8c9e3d Mon Sep 17 00:00:00 2001 From: XSWL1018 <824576966@qq.com> Date: Wed, 19 Jun 2024 09:36:23 +0800 Subject: [PATCH 5/7] init --- .../{DiskFileUtil.java => DiskFileService.java} | 4 ++-- .../common/utils/file/FileOperateUtils.java | 10 +++++----- .../file/{FileUtil.java => FileService.java} | 16 ++++++++-------- ...{MinioFileUtil.java => MinioFileService.java} | 5 ++--- 4 files changed, 17 insertions(+), 18 deletions(-) rename ruoyi-common/src/main/java/com/ruoyi/common/utils/file/{DiskFileUtil.java => DiskFileService.java} (96%) rename ruoyi-common/src/main/java/com/ruoyi/common/utils/file/{FileUtil.java => FileService.java} (95%) rename ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/utils/{MinioFileUtil.java => MinioFileService.java} (94%) diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/DiskFileUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/DiskFileService.java similarity index 96% rename from ruoyi-common/src/main/java/com/ruoyi/common/utils/file/DiskFileUtil.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/file/DiskFileService.java index 43df3b7..51c47b5 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/DiskFileUtil.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/DiskFileService.java @@ -20,12 +20,12 @@ import static com.ruoyi.common.utils.file.FileUtils.getPathFileName; * 磁盘文件操作实现类 */ @Component("file:strategy:disk") -public class DiskFileUtil implements FileUtil { +public class DiskFileService implements FileService { private static String defaultBaseDir = RuoYiConfig.getProfile(); public static void setDefaultBaseDir(String defaultBaseDir) { - DiskFileUtil.defaultBaseDir = defaultBaseDir; + DiskFileService.defaultBaseDir = defaultBaseDir; } public static String getDefaultBaseDir() { diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileOperateUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileOperateUtils.java index 0d1b410..ffa06a1 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileOperateUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileOperateUtils.java @@ -16,7 +16,7 @@ import java.io.OutputStream; */ public class FileOperateUtils { - private static FileUtil fileUtil = SpringUtils.getBean("file:strategy:" + RuoYiConfig.getFileServer()); + private static FileService fileService = SpringUtils.getBean("file:strategy:" + RuoYiConfig.getFileServer()); /** * 默认大小 50M */ @@ -36,7 +36,7 @@ public class FileOperateUtils { public static final String upload(MultipartFile file) throws IOException { try { FileUtils.assertAllowed(file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION); - return fileUtil.upload(file); + return fileService.upload(file); } catch (Exception e) { throw new IOException(e.getMessage(), e); } @@ -53,7 +53,7 @@ public class FileOperateUtils { */ public static final String upload(String filePath, MultipartFile file, String[] allowedExtension) throws Exception { FileUtils.assertAllowed(file, allowedExtension); - return fileUtil.upload(filePath, file); + return fileService.upload(filePath, file); } /** @@ -86,7 +86,7 @@ public class FileOperateUtils { * @throws IOException */ public static final void downLoad(String fileUrl, OutputStream outputStream) throws Exception { - InputStream inputStream = fileUtil.downLoad(fileUrl); + InputStream inputStream = fileService.downLoad(fileUrl); FileUtils.writeBytes(inputStream, outputStream); } @@ -98,6 +98,6 @@ public class FileOperateUtils { * @throws IOException */ public static final boolean deleteFile(String fileUrl) throws Exception { - return fileUtil.deleteFile(fileUrl); + return fileService.deleteFile(fileUrl); } } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileService.java similarity index 95% rename from ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtil.java rename to ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileService.java index 51b8d16..e452b1d 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtil.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileService.java @@ -9,7 +9,7 @@ import java.io.InputStream; /** * 文件操作接口 */ -public interface FileUtil { +public interface FileService { /** * 文件上传 @@ -18,7 +18,7 @@ public interface FileUtil { * @param file 文件对象 * @return 返回上传成功的文路径 * @throws IOException 比如读写文件出错时 - * + * */ public String upload(String filePath, MultipartFile file) throws Exception; @@ -29,17 +29,17 @@ public interface FileUtil { * @param file 文件对象 * @return 返回上传成功的文路径 * @throws IOException 比如读写文件出错时 - * + * */ public String upload(MultipartFile file, String name) throws Exception; /** * 文件上传 - * + * * @param file 文件对象 * @return 返回上传成功的文路径 * @throws IOException 比如读写文件出错时 - * + * */ public String upload(MultipartFile file) throws Exception; @@ -51,7 +51,7 @@ public interface FileUtil { * @param file 文件对象 * @return 返回上传成功的文路径 * @throws IOException 比如读写文件出错时 - * + * */ public String upload(String baseDir, String fileName, MultipartFile file) throws Exception; @@ -61,7 +61,7 @@ public interface FileUtil { * @param filePath 下载的文件路径 * @return 返回上传成功的文路径 * @throws IOException 比如读写文件出错时 - * + * */ public InputStream downLoad(String filePath) throws Exception; @@ -71,7 +71,7 @@ public interface FileUtil { * @param filePath 删除的文件路径 * @return 返回上传成功的文路径 * @throws IOException 比如读写文件出错时 - * + * */ public boolean deleteFile(String filePath) throws Exception; } diff --git a/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/utils/MinioFileUtil.java b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/utils/MinioFileService.java similarity index 94% rename from ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/utils/MinioFileUtil.java rename to ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/utils/MinioFileService.java index 7be7e4f..8555fc4 100644 --- a/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/utils/MinioFileUtil.java +++ b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/utils/MinioFileService.java @@ -1,9 +1,8 @@ package com.ruoyi.middleware.minio.utils; import com.ruoyi.common.config.RuoYiConfig; -import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.file.FileUtil; +import com.ruoyi.common.utils.file.FileService; import com.ruoyi.common.utils.file.FileUtils; import com.ruoyi.common.utils.spring.SpringUtils; import com.ruoyi.middleware.minio.config.MinioConfig; @@ -18,7 +17,7 @@ import java.io.InputStream; * Minio文件操作实现类 */ @Component("file:strategy:minio") -public class MinioFileUtil implements FileUtil { +public class MinioFileService implements FileService { private static MinioConfig minioConfig = SpringUtils.getBean(MinioConfig.class); @Override -- Gitee From 306eb37b5bc5b4f450bb5544e37ab394e0426a7d Mon Sep 17 00:00:00 2001 From: XSWL1018 <824576966@qq.com> Date: Wed, 19 Jun 2024 22:41:38 +0800 Subject: [PATCH 6/7] init --- .../src/main/resources/application-druid.yml | 2 +- .../main/resources/application-middleware.yml | 6 ++--- .../src/main/resources/application.yml | 2 +- .../middleware/minio/config/MinioConfig.java | 23 +++++++------------ 4 files changed, 13 insertions(+), 20 deletions(-) diff --git a/ruoyi-admin/src/main/resources/application-druid.yml b/ruoyi-admin/src/main/resources/application-druid.yml index 758c7d6..56ce492 100644 --- a/ruoyi-admin/src/main/resources/application-druid.yml +++ b/ruoyi-admin/src/main/resources/application-druid.yml @@ -8,7 +8,7 @@ spring: master: url: jdbc:mysql://127.0.0.1/ry?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 username: root - password: WKY20031018 + password: 123456 # 从库数据源 slave: # 从数据源开关/默认关闭 diff --git a/ruoyi-admin/src/main/resources/application-middleware.yml b/ruoyi-admin/src/main/resources/application-middleware.yml index f0122b7..d11800e 100644 --- a/ruoyi-admin/src/main/resources/application-middleware.yml +++ b/ruoyi-admin/src/main/resources/application-middleware.yml @@ -30,6 +30,6 @@ minio: client: master: url: http://localhost:9000 - accessKey: root - secretKey: wky20031018 - defaultBuket: bim-model + accessKey: + secretKey: + defaultBuket: ruoyi diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index 6b2d3c7..4d5c898 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -12,7 +12,7 @@ ruoyi: addressEnabled: false # 验证码类型 math 数组计算 char 字符验证 captchaType: math - + # 指定文件服务类型(值为disk代表使用磁盘作为文件操作服务,minio代表使用minio作为文件操作服务) fileServer: minio # 开发环境配置 diff --git a/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/config/MinioConfig.java b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/config/MinioConfig.java index 012999e..f1c4f96 100644 --- a/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/config/MinioConfig.java +++ b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/config/MinioConfig.java @@ -1,10 +1,16 @@ package com.ruoyi.middleware.minio.config; +import com.ruoyi.common.config.RuoYiConfig; import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.file.FileUtils; import io.minio.MinioClient; +import io.minio.PutObjectArgs; +import io.minio.RemoveObjectArgs; +import io.minio.RemoveObjectsArgs; import io.minio.errors.*; import io.minio.messages.Bucket; import jakarta.annotation.PostConstruct; +import org.apache.http.impl.io.EmptyInputStream; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Configuration; @@ -78,11 +84,6 @@ public class MinioConfig { entity.setClient(build); } catch (Exception exception) { MinioClient build = MinioClient.builder().endpoint(entity.getUrl()).build(); - try { - build.listBuckets(); - } catch (Exception e) { - throw new RuntimeException(e); - } entity.setClient(build); } } @@ -93,16 +94,8 @@ public class MinioConfig { if(StringUtils.isEmpty(defaultBuket)){ throw new RuntimeException("defaultBuket without a default value "); } - List buckets = entity.getClient().listBuckets(); - if (buckets.isEmpty()) { - throw new RuntimeException("minioClient without any buket"); - } - for (Bucket bucket : buckets) { - if (bucket.name().equals(entity.getDefaultBuket())) { - return; - } - } - throw new RuntimeException("configured defaultBucket does not exist"); + RemoveObjectArgs remove = RemoveObjectArgs.builder().bucket(entity.getDefaultBuket()).object("test").build(); + entity.getClient().removeObject(remove); }catch (Exception e){ throw new RuntimeException(e); } -- Gitee From decaec2d5aac2fe80e8a5ad04bb4a1fda4ae8954 Mon Sep 17 00:00:00 2001 From: XSWL1018 <824576966@qq.com> Date: Fri, 21 Jun 2024 18:49:39 +0800 Subject: [PATCH 7/7] init --- .../main/resources/application-middleware.yml | 2 +- .../ruoyi/common/utils/file/FileUtils.java | 3 ++ .../middleware/minio/config/MinioConfig.java | 39 ++++++++++++------- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/ruoyi-admin/src/main/resources/application-middleware.yml b/ruoyi-admin/src/main/resources/application-middleware.yml index d11800e..e7e68a5 100644 --- a/ruoyi-admin/src/main/resources/application-middleware.yml +++ b/ruoyi-admin/src/main/resources/application-middleware.yml @@ -32,4 +32,4 @@ minio: url: http://localhost:9000 accessKey: secretKey: - defaultBuket: ruoyi + defaultBuket: diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java index 70816ed..282e1b9 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java @@ -366,6 +366,9 @@ public class FileUtils { public static final String getRelativePath(String filePath) { Path absolute = Paths.get(filePath); + if (!absolute.isAbsolute()){ + return filePath; + } Path root = absolute.getRoot(); Path normalize = absolute.normalize(); return normalize.subpath(root.getNameCount(), normalize.getNameCount()).toString().replace("\\", "/"); diff --git a/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/config/MinioConfig.java b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/config/MinioConfig.java index f1c4f96..7f9c165 100644 --- a/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/config/MinioConfig.java +++ b/ruoyi-middleware/ruoyi-middleware-minio/src/main/java/com/ruoyi/middleware/minio/config/MinioConfig.java @@ -1,20 +1,21 @@ package com.ruoyi.middleware.minio.config; +import com.ruoyi.common.annotation.Anonymous; import com.ruoyi.common.config.RuoYiConfig; import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.file.FileOperateUtils; import com.ruoyi.common.utils.file.FileUtils; -import io.minio.MinioClient; -import io.minio.PutObjectArgs; -import io.minio.RemoveObjectArgs; -import io.minio.RemoveObjectsArgs; +import io.minio.*; import io.minio.errors.*; import io.minio.messages.Bucket; +import io.minio.messages.Item; import jakarta.annotation.PostConstruct; import org.apache.http.impl.io.EmptyInputStream; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Configuration; +import java.io.File; import java.io.IOException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; @@ -43,7 +44,7 @@ public class MinioConfig { public void init() { List collect = minioClientConfig.getSlave().stream().map(item -> { setClient(item); - isBuketExist(item); + isBuketExistOnAnonymous(item); return item; }).toList(); collect.forEach(item -> { @@ -52,7 +53,7 @@ public class MinioConfig { }); MinioClientConfig.MinioClientEntity master = minioClientConfig.getMaster(); setClient(master); - isBuketExist(master); + isBuketExistOnAnonymous(master); masterClient = master; } @@ -77,25 +78,37 @@ public class MinioConfig { } private static void setClient(MinioClientConfig.MinioClientEntity entity){ - try { + if (StringUtils.isEmpty(entity.getAccessKey())){ + MinioClient build = MinioClient.builder().endpoint(entity.getUrl()).build(); + entity.setClient(build); + }else { MinioClient build = MinioClient.builder().endpoint(entity.getUrl()) .credentials(entity.getAccessKey(), entity.getSecretKey()).build(); - build.listBuckets(); entity.setClient(build); - } catch (Exception exception) { - MinioClient build = MinioClient.builder().endpoint(entity.getUrl()).build(); + BucketExistsArgs bucketExistArgs = BucketExistsArgs.builder().bucket(entity.getDefaultBuket()).build(); + try { + boolean b = entity.getClient().bucketExists(bucketExistArgs); + if (!b){ + throw new RuntimeException("defaultBucket does not exist"); + } + } catch (Exception e) { + throw new RuntimeException(e.getMessage()); + } entity.setClient(build); } } - private static void isBuketExist(MinioClientConfig.MinioClientEntity entity) { + + private static void isBuketExistOnAnonymous(MinioClientConfig.MinioClientEntity entity) { try { String defaultBuket = entity.getDefaultBuket(); if(StringUtils.isEmpty(defaultBuket)){ throw new RuntimeException("defaultBuket without a default value "); } - RemoveObjectArgs remove = RemoveObjectArgs.builder().bucket(entity.getDefaultBuket()).object("test").build(); - entity.getClient().removeObject(remove); + PutObjectArgs putObjectArgs= PutObjectArgs.builder().object(FileUtils.getRelativePath(RuoYiConfig.getProfile())+ "/") + .stream(EmptyInputStream.nullInputStream(),0,-1).bucket(entity.getDefaultBuket()).build(); + entity.getClient().putObject(putObjectArgs); + }catch (Exception e){ throw new RuntimeException(e); } -- Gitee