| | |
| | | package org.dromara.demo.util; |
| | | |
| | | |
| | | import io.minio.*; |
| | | import io.minio.messages.DeleteError; |
| | | import io.minio.messages.DeleteObject; |
| | | import io.minio.messages.Item; |
| | | import jakarta.servlet.ServletOutputStream; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import org.apache.commons.compress.utils.IOUtils; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.http.HttpHeaders; |
| | | import org.springframework.http.HttpStatus; |
| | | import org.springframework.http.MediaType; |
| | | import org.springframework.http.ResponseEntity; |
| | | import cn.hutool.core.util.IdUtil; |
| | | import io.minio.MinioClient; |
| | | import io.minio.PutObjectOptions; |
| | | import jakarta.annotation.PostConstruct; |
| | | import lombok.Data; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.dromara.demo.domain.MinioResult; |
| | | import org.dromara.demo.exception.UploadFailException; |
| | | import org.springframework.boot.context.properties.ConfigurationProperties; |
| | | import org.springframework.stereotype.Component; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.io.ByteArrayOutputStream; |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | import java.io.UnsupportedEncodingException; |
| | | import java.net.URLEncoder; |
| | | import java.nio.charset.StandardCharsets; |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | import java.util.stream.Collectors; |
| | | import java.io.ByteArrayInputStream; |
| | | |
| | | /** |
| | | * @description: minio工具类 |
| | | * @version |
| | | * @author gonghl |
| | | * @date 2024-3-6 |
| | | */ |
| | | @Component |
| | | @ConfigurationProperties(prefix = "minio") |
| | | @Slf4j |
| | | @Data |
| | | public class MinioUtil { |
| | | @Autowired |
| | | private MinioClient minioClient; |
| | | |
| | | @Value("${minio.bucketName}") |
| | | private String bucketName; |
| | | /** |
| | | * description: 判断bucket是否存在,不存在则创建 |
| | | * |
| | | * @return: void |
| | | */ |
| | | public void existBucket(String name) { |
| | | |
| | | private String url; |
| | | private String accessKey; |
| | | private String secretKey; |
| | | private MinioClient client; |
| | | |
| | | |
| | | public MinioResult uploadFile(MultipartFile file, String bucketName) { |
| | | try { |
| | | boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(name).build()); |
| | | if (!exists) { |
| | | minioClient.makeBucket(MakeBucketArgs.builder().bucket(name).build()); |
| | | if (!client.bucketExists(bucketName)) { |
| | | client.makeBucket(bucketName); |
| | | client.setBucketPolicy(bucketName, "public"); |
| | | } |
| | | |
| | | String[] split = file.getOriginalFilename().split("\\."); |
| | | String suffix = split[split.length - 1]; |
| | | |
| | | if (split.length < 2) { |
| | | suffix = ""; |
| | | } |
| | | |
| | | String fileName = StringUtils.join(IdUtil.randomUUID(), ".", suffix); |
| | | |
| | | client.putObject(bucketName, fileName, file.getInputStream(), new PutObjectOptions(file.getSize(), 5 * 1024 * 1024)); |
| | | String fileUrl = getFilePath(bucketName, fileName); |
| | | if (StringUtils.isNotBlank(fileUrl)) { |
| | | return new MinioResult(bucketName, fileName, fileUrl, file.getOriginalFilename(), null); |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | log.error("上传失败,失败详情信息:{}", e.getMessage()); |
| | | throw new UploadFailException(); |
| | | } |
| | | return null; |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 创建存储bucket |
| | | * @param bucketName 存储bucket名称 |
| | | * @return Boolean |
| | | */ |
| | | public Boolean makeBucket(String bucketName) { |
| | | public MinioResult uploadFile(ByteArrayInputStream in, String name, String bucketName) { |
| | | |
| | | String[] split = name.split("\\."); |
| | | String suffix = split[split.length - 1]; |
| | | if (split.length < 2) { |
| | | suffix = ""; |
| | | } |
| | | String fileName = StringUtils.join(IdUtil.randomUUID(), ".", suffix); |
| | | try { |
| | | minioClient.makeBucket(MakeBucketArgs.builder() |
| | | .bucket(bucketName) |
| | | .build()); |
| | | client.putObject(bucketName, fileName, in, new PutObjectOptions(in.available(), 5 * 1024 * 1024)); |
| | | String fileUrl = getFilePath(bucketName, fileName); |
| | | if (StringUtils.isNotBlank(fileUrl)) { |
| | | return new MinioResult(bucketName, fileName, fileUrl, name, null); |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return false; |
| | | log.error("上传失败,失败详情信息:{}", e.getMessage()); |
| | | throw new UploadFailException(); |
| | | } |
| | | return true; |
| | | |
| | | return null; |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 删除存储bucket |
| | | * @param bucketName 存储bucket名称 |
| | | * @return Boolean |
| | | */ |
| | | public Boolean removeBucket(String bucketName) { |
| | | public String uploadImage(ByteArrayInputStream in, String bucketName) { |
| | | try { |
| | | minioClient.removeBucket(RemoveBucketArgs.builder() |
| | | .bucket(bucketName) |
| | | .build()); |
| | | String fileName = IdUtil.randomUUID() + ".jpg"; |
| | | client.putObject(bucketName, fileName, in, new PutObjectOptions(in.available(), 5 * 1024 * 1024)); |
| | | String fileUrl = getFilePath(bucketName, fileName); |
| | | if (StringUtils.isNotBlank(fileUrl)) { |
| | | return fileUrl; |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return false; |
| | | log.error("上传失败,失败详情信息:{}", e.getMessage()); |
| | | throw new UploadFailException(); |
| | | } |
| | | return true; |
| | | } |
| | | /** |
| | | * description: 上传文件 |
| | | * |
| | | * @param multipartFile |
| | | * @return: java.lang.String |
| | | |
| | | */ |
| | | public List<String> uploads(MultipartFile[] multipartFile) { |
| | | List<String> names = new ArrayList<>(multipartFile.length); |
| | | for (MultipartFile file : multipartFile) { |
| | | String fileName = file.getOriginalFilename(); |
| | | String[] split = fileName.split("\\."); |
| | | if (split.length > 1) { |
| | | fileName = split[0] + "_" + System.currentTimeMillis() + "." + split[1]; |
| | | } else { |
| | | fileName = fileName + System.currentTimeMillis(); |
| | | } |
| | | InputStream in = null; |
| | | try { |
| | | in = file.getInputStream(); |
| | | minioClient.putObject(PutObjectArgs.builder() |
| | | .bucket(bucketName) |
| | | .object(fileName) |
| | | .stream(in, in.available(), -1) |
| | | .contentType(file.getContentType()) |
| | | .build() |
| | | ); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } finally { |
| | | if (in != null) { |
| | | try { |
| | | in.close(); |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | } |
| | | names.add(fileName); |
| | | } |
| | | return names; |
| | | return null; |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 上传单个文件 |
| | | * @param multipartFile |
| | | * @return |
| | | */ |
| | | public String upload(MultipartFile multipartFile) { |
| | | |
| | | String fileName = multipartFile.getOriginalFilename(); |
| | | String[] split = fileName.split("\\."); |
| | | if (split.length > 1) { |
| | | fileName = split[0] + "_" + System.currentTimeMillis() + "." + split[1]; |
| | | } else { |
| | | fileName = fileName + System.currentTimeMillis(); |
| | | } |
| | | InputStream in = null; |
| | | try { |
| | | in = multipartFile.getInputStream(); |
| | | minioClient.putObject(PutObjectArgs.builder() |
| | | .bucket(bucketName) |
| | | .object(fileName) |
| | | .stream(in, in.available(), -1) |
| | | .contentType(multipartFile.getContentType()) |
| | | .build() |
| | | ); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } finally { |
| | | if (in != null) { |
| | | try { |
| | | in.close(); |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | return fileName; |
| | | } |
| | | |
| | | /** |
| | | * description: 下载文件 |
| | | * |
| | | * @param fileName |
| | | * @return: org.springframework.http.ResponseEntity<byte [ ]> |
| | | */ |
| | | public ResponseEntity<byte[]> download(String fileName) { |
| | | ResponseEntity<byte[]> responseEntity = null; |
| | | InputStream in = null; |
| | | ByteArrayOutputStream out = null; |
| | | public String getFilePath(String bucketName, String fileName) { |
| | | String wordUrl = null; |
| | | try { |
| | | in = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(fileName).build()); |
| | | out = new ByteArrayOutputStream(); |
| | | IOUtils.copy(in, out); |
| | | //封装返回值 |
| | | byte[] bytes = out.toByteArray(); |
| | | HttpHeaders headers = new HttpHeaders(); |
| | | try { |
| | | headers.add("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); |
| | | } catch (UnsupportedEncodingException e) { |
| | | e.printStackTrace(); |
| | | if (client.getObject(bucketName, fileName) == null) { |
| | | return null; |
| | | } |
| | | headers.setContentLength(bytes.length); |
| | | headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); |
| | | headers.setAccessControlExposeHeaders(Arrays.asList("*")); |
| | | responseEntity = new ResponseEntity<byte[]>(bytes, headers, HttpStatus.OK); |
| | | |
| | | return StringUtils.join("/", bucketName, "/", fileName); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } finally { |
| | | try { |
| | | if (in != null) { |
| | | try { |
| | | in.close(); |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | if (out != null) { |
| | | out.close(); |
| | | } |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | log.error("获取bucket为:{},文件名为{}时出错,原因:{}", bucketName, fileName, e.getMessage()); |
| | | } |
| | | return responseEntity; |
| | | } |
| | | |
| | | /** |
| | | * 下载文件 |
| | | * |
| | | * @param originalName 文件路径 |
| | | */ |
| | | public InputStream downloadFile(String originalName, HttpServletResponse response) { |
| | | try { |
| | | |
| | | InputStream file = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(originalName).build()); |
| | | String filename = new String(originalName.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8); |
| | | if (StringUtils.isNotBlank(originalName)) { |
| | | filename = originalName; |
| | | } |
| | | response.setHeader("Content-Disposition", "attachment;filename=" + filename); |
| | | ServletOutputStream servletOutputStream = response.getOutputStream(); |
| | | int len; |
| | | byte[] buffer = new byte[1024]; |
| | | while ((len = file.read(buffer)) > 0) { |
| | | servletOutputStream.write(buffer, 0, len); |
| | | } |
| | | servletOutputStream.flush(); |
| | | file.close(); |
| | | servletOutputStream.close(); |
| | | return file; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return null; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 批量删除文件对象 |
| | | * @param bucketName 存储bucket名称 |
| | | * @param objects 对象名称集合 |
| | | */ |
| | | public Iterable<Result<DeleteError>> removeObjects(String bucketName, List<String> objects) { |
| | | List<DeleteObject> dos = objects.stream().map(e -> new DeleteObject(e)).collect(Collectors.toList()); |
| | | Iterable<Result<DeleteError>> results = minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(dos).build()); |
| | | return results; |
| | | } |
| | | @PostConstruct |
| | | public void creatConnect() throws Exception { |
| | | this.client = new MinioClient(url, accessKey, secretKey); |
| | | |
| | | |
| | | } |
| | | |
| | | } |
| | | |
| | | |