安装参考
https://blog.csdn.net/qq_29752857/article/details/130337394
一、依赖
<!--minio--> <dependency> <groupId>io.minio</groupId> <artifactId>minio</artifactId> <version>8.5.2</version> </dependency> <!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp --> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>4.10.0</version> </dependency> <!-- lombok需要安装插件 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency>
二、配置文件
spring: # 配置文件上传大小限制 servlet: multipart: max-file-size: 200MB max-request-size: 200MB minio: endpoint: http://127.0.0.1:9000 accessKey: root secretKey: rootroot bucketName: project1
import io.minio.MinioClient; import lombok.Data; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; @Data @Component public class MinIoClientConfig { @Value("${minio.endpoint}") private String endpoint; @Value("${minio.accessKey}") private String accessKey; @Value("${minio.secretKey}") private String secretKey; /** * 注入minio 客户端 * * @return */ @Bean public MinioClient minioClient() { return MinioClient.builder() .endpoint(endpoint) .credentials(accessKey, secretKey) .build(); } }
三、操作工具类
import io.minio.*; import io.minio.http.Method; import io.minio.messages.Bucket; import io.minio.messages.DeleteError; import io.minio.messages.DeleteObject; import io.minio.messages.Item; import lombok.SneakyThrows; import org.apache.commons.compress.utils.IOUtils; 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 org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.*; import java.util.stream.Collectors; /** * @description: minio工具类 * @version:3.0 */ @Component public class MinioUtil { @Autowired private MinioClient minioClient; @Value("${minio.bucketName}") private String bucketName; /** * description: 判断bucket是否存在,不存在则创建 * * @return: void */ public void existBucket(String name) { try { boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(name).build()); if (!exists) { minioClient.makeBucket(MakeBucketArgs.builder().bucket(name).build()); } } catch (Exception e) { e.printStackTrace(); } } /** * 创建存储bucket * * @param bucketName 存储bucket名称 * @return Boolean */ public Boolean makeBucket(String bucketName) { try { minioClient.makeBucket(MakeBucketArgs.builder() .bucket(bucketName) .build()); } catch (Exception e) { e.printStackTrace(); return false; } return true; } /** * 删除存储bucket * * @param bucketName 存储bucket名称 * @return Boolean */ public Boolean removeBucket(String bucketName) { try { minioClient.removeBucket(RemoveBucketArgs.builder() .bucket(bucketName) .build()); } catch (Exception e) { e.printStackTrace(); return false; } return true; } /** * description: 上传文件 * * @param multipartFile * @return: java.lang.String */ public List<String> upload(MultipartFile[] multipartFile) { return upload(multipartFile, bucketName,""); } /** * description: 上传文件 * * @param multipartFile * @return: java.lang.String */ public List<String> upload(MultipartFile[] multipartFile,String filePath) { return upload(multipartFile, bucketName,filePath); } /** * description: 上传文件 * * @param multipartFile * @return: java.lang.String */ public List<String> upload(MultipartFile[] multipartFile, String bucketName,String filePath) { List<String> names = new ArrayList<>(multipartFile.length); for (MultipartFile file : multipartFile) { String fileName = file.getOriginalFilename(); String[] split = fileName.split("\\."); if (split.length > 1) { StringBuilder filenameTem = new StringBuilder(); for (int i = 0; i < split.length; i++) { if (i != split.length - 1) { filenameTem.append(split[i]); } else { filenameTem.append("_" + System.currentTimeMillis() + "." + split[split.length - 1]); } } fileName = filenameTem.toString(); } else { fileName = fileName + System.currentTimeMillis(); } InputStream in = null; try { in = file.getInputStream(); minioClient.putObject(PutObjectArgs.builder() .bucket(bucketName) .object(filePath+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; } /** * 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; 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(); } headers.setContentLength(bytes.length); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); headers.setAccessControlExposeHeaders(Arrays.asList("*")); responseEntity = new ResponseEntity<byte[]>(bytes, headers, HttpStatus.OK); } 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(); } } return responseEntity; } /** * 查看文件对象 * * @param bucketName 存储bucket名称 * @return 存储bucket内文件对象信息 */ public List<HashMap<String,Object>> listObjects(String bucketName) { Iterable<Result<Item>> results = minioClient.listObjects( ListObjectsArgs.builder().bucket(bucketName).build()); List<HashMap<String,Object>> objectItems = new ArrayList<>(); try { for (Result<Item> result : results) { Item item = result.get(); HashMap<String,Object> objectItem = new HashMap<>(); objectItem.put("name",item.objectName()); objectItem.put("size",item.size()); objectItems.add(objectItem); } } catch (Exception e) { e.printStackTrace(); return null; } return objectItems; } /** * 批量删除文件对象 * * @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; } /** * 判断桶是否存在 */ @SneakyThrows(Exception.class) public boolean bucketExists(String bucketName) { return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build()); } /** * 创建桶 * * @param bucketName 获取全部的桶 minioClient.listBuckets(); */ @SneakyThrows(Exception.class) public void createBucket(String bucketName) { if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) { minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build()); } } /** * 根据bucketName获取信息 * * @param bucketName bucket名称 */ @SneakyThrows(Exception.class) public Optional<Bucket> getBucket(String bucketName) { return minioClient.listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst(); } /** * 获取文件流 * * @param bucketName bucket名称 * @param objectName 文件名称 * @return 二进制流 */ @SneakyThrows(Exception.class) public InputStream getObject(String bucketName, String objectName) { return minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build()); } /** * 上传本地文件 * * @param bucketName 存储桶 * @param objectName 对象名称 * @param fileName 本地文件路径 */ @SneakyThrows(Exception.class) public ObjectWriteResponse putObject(String bucketName, String objectName, String fileName) { if (!bucketExists(bucketName)) { createBucket(bucketName); } return minioClient.uploadObject(UploadObjectArgs.builder().bucket(bucketName).object(objectName).filename(fileName).build()); } /** * 通过流上传文件 * * @param bucketName 存储桶 * @param objectName 文件对象 * @param inputStream 文件流 */ @SneakyThrows(Exception.class) public ObjectWriteResponse putObject(String bucketName, String objectName, InputStream inputStream) { if (!bucketExists(bucketName)) { createBucket(bucketName); } return minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(inputStream, inputStream.available(), -1).build()); } /** * 获取文件外链 * @param objectName 文件名称 * @return url */ @SneakyThrows(Exception.class) public String getUploadObjectUrl(String objectName) { return getUploadObjectUrl(objectName,60*60); } /** * 获取文件外链 * @param objectName 文件名称 * @param expires 过期时间 * @return url */ @SneakyThrows(Exception.class) public String getUploadObjectUrl(String objectName, Integer expires) { return getUploadObjectUrl(bucketName,objectName,expires); } /** * 获取文件外链 * * @param bucketName bucket名称 * @param objectName 文件名称 * @param expires 过期时间 * @return url */ @SneakyThrows(Exception.class) public String getUploadObjectUrl(String bucketName, String objectName, Integer expires) { return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder() .method(Method.PUT).bucket(bucketName) .object(objectName).expiry(expires).build()); } /** * 下载文件 * bucketName:桶名 * * @param fileName: 文件名 */ @SneakyThrows(Exception.class) public void download(String bucketName, String fileName, HttpServletResponse response) { // 获取对象的元数据 StatObjectResponse stat = minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(fileName).build()); response.setContentType(stat.contentType()); response.setCharacterEncoding("UTF-8"); response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); InputStream is = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(fileName).build()); IOUtils.copy(is, response.getOutputStream()); is.close(); } }
四、测试代码
@RestController @Slf4j public class MinioController { @Autowired private MinioUtil minioUtil; @Value("${minio.endpoint}") private String address; @Value("${minio.bucketName}") private String bucketName; @PostMapping("/upload") public String upload(MultipartFile file,String filePath) { List<String> upload = minioUtil.upload(new MultipartFile[]{file},filePath); return address + "/" + bucketName + "/" +filePath+ upload.get(0); } @PostMapping("/uploadList") public List<String> uploadList(MultipartFile[] file) { List<String> upload = minioUtil.upload(file); upload = upload.stream().map(it -> address + "/" + bucketName + "/" + it).collect(Collectors.toList()); return upload; } @GetMapping("/getUrl") public String get(String objectName) { return minioUtil.getUploadObjectUrl(objectName); } @GetMapping("/down") public ResponseEntity<byte[]> down(String objectName) { return minioUtil.download(objectName); } }