springboot如何整合minio呢?

戚薇 SpringBoot 发布时间:2023-05-08 09:36:47 阅读数:15234 1
下文笔者讲述SpringBoot中整合minio的方法及示例分享,如下所示

SpringBoot整合minio的实现思路

1.添加依赖
2.设置相应的配置文件
3.编写minio配置类
4.编写minio工具类
5.编写控制器代码
例:SpringBoot使用minio的示例

第一步:添加依赖

<dependency>
    <groupId>io.minio</groupId>
    <artifactId>minio</artifactId>
    <version>8.4.3</version>
</dependency>
 

第二步:application.yml配置

spring:
  # 配置文件上传大小限制
  servlet:
    multipart:
      max-file-size: 200MB
      max-request-size: 200MB
minio:
  endpoint: http://127.0.0.1:9005
  accessKey: minioadmin
  secretKey: minioadmin
  bucketName: java265-simple

第三步:编写minio配置类

@Configuration
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();
    }
}

第四步:minio工具类

@Slf4j
@Component
public class MinioUtil {
    @Resource
    private MinioClient minioClient;

    @Value("${minio.bucketName}")
    private String bucketName;

     桶操作 /

    /**
     * 查看bucket是否存在
     * @return boolean
     */
    public boolean bucketExists(String bucketName) {
        try {
            return minioClient.bucketExists(BucketExistsArgs.builder()
                    .bucket(bucketName)
                    .build());
        } catch (Exception e) {
            log.error("查看bucket是否存在", e);
            return false;
        }
    }

    /**
     * 创建存储bucket
     * @return Boolean
     */
    public boolean createBucket(String bucketName) {
        if (bucketExists(bucketName)) {
            return true;
        }
        try {
            minioClient.makeBucket(MakeBucketArgs.builder()
                    .bucket(bucketName)
                    .build());
            return true;
        } catch (Exception e) {
            log.error("创建桶失败", e);
            return false;
        }
    }

    /**
     * 删除存储bucket
     *
     * @return boolean
     */
    public boolean removeBucket(String bucketName) {
        if (!bucketExists(bucketName)) {
            return true;
        }
        //获取桶中所有的对象
        list<Item> items = getBucketObjects(bucketName);
        if (items.size() > 0) {
            //有对象文件,则删除失败
            return false;
        }
        try {
            minioClient.removeBucket(RemoveBucketArgs.builder()
                    .bucket(bucketName)
                    .build());
            return true;
        } catch (Exception e) {
            log.error("根据名称删除桶失败", e);
            return false;
        }
    }

    /**
     * 获取存储桶策略
     *
     * @param bucketName 存储桶名称
     * @return json
     */
    public String getBucketPolicy(String bucketName) {
        String bucketPolicy = null;
        try {
            bucketPolicy = minioClient.getBucketPolicy(GetBucketPolicyArgs.builder()
                    .bucket(bucketName)
                    .build());
        } catch (Exception e) {
            log.error("获取存储桶策略失败", e);
        }
        return bucketPolicy;
    }

    /**
     * 根据bucketName获取信息
     *
     * @param bucketName bucket名称
     *
     * return 如果不存在返回null
     */
    public Bucket getBucket(String bucketName) {
        try {
            return minioClient.listBuckets()
                    .stream()
                    .filter(b -> b.name().equals(bucketName))
                    .findFirst()
                    .orElse(null);
        } catch (Exception e) {
            log.error("根据bucketName获取桶信息", e);
        }
        return null;
    }

    /**
     * 获取全部bucket
     */
    public List<Bucket> getAllBuckets() {
        try {
            return minioClient.listBuckets();
        } catch (Exception e) {
            log.error("获取所有的桶信息", e);
        }
        return null;
    }

    /**
     * 创建文件夹或目录
     *
     * @param directoryName 目录路径
     */
    public boolean createDirectory(String bucketName, String directoryName) {
        if (!bucketExists(bucketName)) {
            createBucket(bucketName);
        }

        try {
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(directoryName)
                    .stream(new ByteArrayInputStream(new byte[]{}), 0, -1)
                    .build());
            return true;
        } catch (Exception e) {
            log.error("创建文件夹或目录失败", e);
            return false;
        }
    }

    / 文件操作 ///

    /**
     * 判断文件是否存在
     *
     * @param bucketName 存储桶
     * @param objectName 对象
     * @return 存在返回true,不存在发生异常返回false
     */
    public boolean objectExist(String bucketName, String objectName) {
        if (!bucketExists(bucketName)) {
            return false;
        }
        try {
            minioClient.statObject(StatObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .build());
            return true;
        } catch (Exception e) {
            log.error("判断文件是否存在失败", e);
            return false;
        }
    }

    /**
     * 判断文件夹是否存在【注意是文件夹而不是目录】
     * @param folderName 文件夹名称(去掉前后的/)
     * @return
     */
    public boolean folderExist(String bucketName, String folderName) {
        if (!bucketExists(bucketName)) {
            return false;
        }
        try {
            Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder()
                    .bucket(bucketName)
                    .prefix(folderName)
                    .recursive(false)
                    .build());
            if (results != null) {
                for (Result<Item> result : results) {
                    Item item = result.get();
                    folderName += "/";
                    if (item.isDir() && folderName.equals(item.objectName())) {
                        return true;
                    }
                }
            }
        } catch (Exception e) {
            log.error("判断文件夹是否存在失败", e);
            return false;
        }
        return false;
    }

    /**
     * 文件上传
     * @param multipartFile 待上传文件
     * @param folderName 目录
     * @param aimFileName 最终保存到minio中的文件名,不需要后缀
     * @return
     */
    public String putObject(String bucketName, MultipartFile multipartFile, String folderName, String aimFileName) {
        if (!bucketExists(bucketName)) {
            createBucket(bucketName);
        }

        if (!StringUtils.hasText(aimFileName)) {
            aimFileName = UUID.randomUUID().toString();
        }
        //获取文件后缀
        String originalFilename = multipartFile.getOriginalFilename();
        String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
        aimFileName += suffix;

        //带路径的文件名
        String lastFileName = "";
        if (StringUtils.hasText(folderName)) {
            lastFileName = "/" + folderName + "/" + aimFileName;
        } else {
            lastFileName = aimFileName;
        }

        try (InputStream inputStream = multipartFile.getInputStream();) {
            //上传文件到指定目录,文件名称相同会覆盖
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(lastFileName)
                    .stream(inputStream, multipartFile.getSize(), -1)
                    .contentType(multipartFile.getContentType())
                    .build());
            return getObjectUrl(bucketName, lastFileName);
        } catch (Exception e) {
            log.error("文件上传失败", e);
            return null;
        }

    }

    /**
     * 上传文件【不指定文件夹】
     * @param multipartFile
     * @param fileName
     * @return
     */
    public String putObject(String bucketName, MultipartFile multipartFile, String fileName) {
        return putObject(bucketName, multipartFile, null, fileName);
    }

    /**
     * 上传文件【不指定文件夹,不指定目标文件名】
     * @param multipartFile
     * @return
     */
    public String putObject(String bucketName, MultipartFile multipartFile) {
        return putObject(bucketName, multipartFile, null, null);
    }

    /**
     * 自动创建桶并存储文件
     *
     * @param inputStream
     * @param aimFileName 必须,minio桶中文件的名字,需要带后缀
     * @return
     */
    public String putObject(String bucketName, InputStream inputStream, String aimFileName) {
        if (!bucketExists(bucketName)) {
            createBucket(bucketName);
        }
        try {
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(aimFileName)
                    .stream(inputStream, inputStream.available(), -1)
                    .build();
            minioClient.putObject(putObjectArgs);
            inputStream.close();
            return getObjectUrl(bucketName, aimFileName);
        } catch (Exception e) {
            log.error("文件上传失败", e);
            return null;
        }
    }

    /**
     * 拷贝文件
     *
     * @param bucketName    bucket名称
     * @param objectName    文件名称
     * @param srcBucketName 目标bucket名称
     * @param srcObjectName 目标文件名称
     */
    public boolean copyObject(String srcBucketName, String srcObjectName, String bucketName, String objectName) {
        try {
            minioClient.copyObject(
                    CopyObjectArgs.builder()
                            .source(CopySource.builder()
                                    .bucket(srcBucketName)
                                    .object(srcObjectName)
                                    .build())
                            .bucket(bucketName)
                            .object(objectName)
                            .build());
            return true;
        } catch (Exception e) {
            log.error("拷贝文件失败", e);
            return false;
        }
    }

    /**
     * 文件下载
     * @param fileName 文件名称
     * @param response response
     * @return Boolean
     */
    public void getObject(String bucketName, String fileName, HttpServletResponse response) {
        if (!bucketExists(bucketName)) {
            return;
        }
        GetObjectArgs getObjectArgs = GetObjectArgs.builder()
                .bucket(bucketName)
                .object(fileName)
                .build();

        try (ServletOutputStream outputStream = response.getOutputStream();
             GetObjectResponse objectResponse = minioClient.getObject(getObjectArgs)) {

            response.setCharacterEncoding("utf-8");
            //设置强行下载不打开
            //response.setContentType("application/force-download");
            //response.setContentType("APPLICATION/OCTET-STREAM");
            response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
            ByteStreams.copy(objectResponse, outputStream);
            outputStream.flush();
        } catch (Exception e) {
            log.error("文件下载失败", e);
        }
    }

    /**
     * 以流的形式获取一个文件对象
     *
     * @param objectName 对象名称
     * @return {@link InputStream}
     */
    public InputStream getObject(String bucketName, String objectName) {
        if (!bucketExists(bucketName)) {
            return null;
        }
        try {
            StatObjectResponse statObjectResponse = minioClient.statObject(StatObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .build());
            if (statObjectResponse.size() > 0) {
                // 获取objectName的输入流。
                return minioClient.getObject(GetObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .build());
            }
        } catch (Exception e) {
            log.error("文件下载失败", e);
        }
        return null;
    }

    /**
     * 获取文件信息, 如果抛出异常则说明文件不存在
     *
     * @param objectName 文件名称
     */
    public StatObjectResponse getObjectInfo(String bucketName, String objectName) {
        if (!bucketExists(bucketName)) {
            return null;
        }

        StatObjectResponse statObjectResponse = null;
        try {
            statObjectResponse = minioClient.statObject(StatObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .build());
        } catch (Exception e) {
            log.error("获取文件信息失败", e);
        }
        return statObjectResponse;
    }

    /**
     * 获取图片的路径
     *
     * @param fileName
     * @return
     */
    public String getObjectUrl(String bucketName, String fileName) {
        try {
            if (fileName.startsWith("/")) {
                fileName = fileName.substring(1);
            }
            GetPresignedObjectUrlArgs build = GetPresignedObjectUrlArgs.builder()
                    .bucket(bucketName)
                    .object(fileName)
                    .method(Method.GET)
                    //过期时间(分钟数)
                    .expiry(60 * 60)
                    .build();
            return minioClient.getPresignedObjectUrl(build);
        } catch (Exception e) {
            log.error("获取文件路径失败", e);
        }
        return null;
    }

    /**
     * 断点下载
     *
     * @param objectName 文件名称
     * @param offset     起始字节的位置
     * @param length     要读取的长度
     * @return 流
     */
    public InputStream getObject(String bucketName, String objectName, long offset, long length) {
        if (!bucketExists(bucketName)) {
            return null;
        }
        GetObjectResponse objectResponse = null;
        try {
            objectResponse = minioClient.getObject(GetObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .offset(offset)
                    .length(length)
                    .build());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return objectResponse;
    }

    /**
     * 获取指定桶中的所有文件对象
     *
     * @return 存储bucket内文件对象信息
     */
    public List<Item> getBucketObjects(String bucketName) {
        if (!bucketExists(bucketName)) {
            return null;
        }

        List<Item> items = new ArrayList<>();

        Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder()
                .bucket(bucketName)
                .build());
        if (results != null) {
            try {
                for (Result<Item> result : results) {
                    items.add(result.get());
                }
            } catch (Exception e) {
                log.error("获取指定桶中的所有文件对象", e);
            }
        }
        return items;
    }

    /**
     * 获取路径下文件列表
     *
     * @param prefix     路径名称
     * @param recursive  是否递归查找,如果是false,就模拟文件夹结构查找
     * @return 二进制流
     */
    public Iterable<Result<Item>> getObjects(String bucketName, String prefix, boolean recursive) {
        if (!bucketExists(bucketName)) {
            return null;
        }
        Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder()
                .bucket(bucketName)
                .prefix(prefix)
                .recursive(recursive)
                .build());
        return results;
    }

    /**
     * 根据文件前置查询文件
     *
     * @param prefix     前缀
     * @param recursive  是否递归查询
     * @return MinioItem 列表
     */
    public List<Item> getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive) {
        if (!bucketExists(bucketName)) {
            return null;
        }
        List<Item> items = new ArrayList<>();
        Iterable<Result<Item>> objectsIterator = minioClient.listObjects(
                ListObjectsArgs.builder()
                        .bucket(bucketName)
                        .prefix(prefix)
                        .recursive(recursive)
                        .build());
        if (objectsIterator != null) {
            try {
                for (Result<Item> o : objectsIterator) {
                    Item item = o.get();
                    items.add(item);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return items;
    }

    /**
     * 删除文件
     * @param fileName 文件名
     * @return
     * @throws Exception
     */
    public boolean removeObject(String bucketName, String fileName) {
        if (!bucketExists(bucketName)) {
            return false;
        }
        try {
            minioClient.removeObject(RemoveObjectArgs.builder()
                    .bucket(bucketName)
                    .object(fileName)
                    .build());
            return true;
        } catch (Exception e) {
            log.error("根据文件删除文件失败", e);
            return false;
        }
    }

    /**
     * 批量删除文件对象【没有测试成功】
     * @param objects 需要删除的文件列表
     */
    public boolean removeObjects(String bucketName, String... objects) {
        if (!bucketExists(bucketName)) {
            return false;
        }
        List<DeleteObject> deleteObjects = new LinkedList<>();
        Arrays.stream(objects).forEach(s -> {
            deleteObjects.add(new DeleteObject(s));
        });

        Iterable<Result<DeleteError>> results = minioClient.removeObjects(RemoveObjectsArgs.builder()
                .bucket(bucketName)
                .objects(deleteObjects)
                .build());

        //Minio处理批量删除的时候, 采用的延迟执行, 需要通过迭代返回的Iterable<Result<DeleteError>>以执行删除
        if (results != null) {
            try {
                for (Result<DeleteError> result : results) {
                    DeleteError error = result.get();
                    log.error("Error in deleting object " + error.objectName() + "; " + error.message());
                }
            } catch (Exception e) {
                log.error("批量删除文件失败", e);
            }
        }

        return true;
    }

}

第五步:Controller编写

@RestController
@RequestMapping("/minio")
public class MinioController {
    @Resource
    private MinioUtil minioUtil;

    /**
     * 添加桶
     */
    @GetMapping(value = "/create/{bucketName}")
    public String create(@PathVariable("bucketName") String bucketName) {
        minioUtil.createBucket(bucketName);
        return "创建成功";
    }

    /**
     * 检查桶是否存在
     */
    @GetMapping(value = "/exist/{bucketName}")
    public String exist(@PathVariable("bucketName") String bucketName) {
        boolean exists = minioUtil.bucketExists(bucketName);
        return "存在:" + exists;
    }

    /**
     * 删除桶
     */
    @GetMapping(value = "/remove/{bucketName}")
    public String remove(@PathVariable("bucketName") String bucketName) {
        boolean res = minioUtil.removeBucket(bucketName);
        return "删除:" + res;
    }

    /**
     * 获取所有的桶
     * @return
     */
    @GetMapping(value = "/getAllBuckets")
    public List<Bucket> getAllBuckets() {
        List<Bucket> allBuckets = minioUtil.getAllBuckets();
        return allBuckets;
    }

    /**
     * 上传图片,直接上传的跟目录
     * @param file
     * @return
     */
    @PostMapping("/upload1")
    public String upload1(MultipartFile file) {
        if (file.isEmpty() || file.getSize() == 0) {
            return "文件为空";
        }
        try {
            String newName = "";
            String fileUrl = minioUtil.putObject("java265-simple", file, newName);
            return fileUrl;
        } catch (Exception e) {
            e.printStackTrace();
            return "上传失败";
        }
    }

    /**
     * 上传图片,指定上传到的目录及重命名
     * @param file
     * @return
     */
    @PostMapping("/upload2")
    public String upload2(MultipartFile file) {
        if (file.isEmpty() || file.getSize() == 0) {
            return "文件为空";
        }
        try {
            String newName = "静静";
            String fileUrl = minioUtil.putObject("java265-simple", file, "haha/xixi", newName);
            return fileUrl;
        } catch (Exception e) {
            e.printStackTrace();
            return "上传失败";
        }
    }

    /**
     * 获取图片的路径【带问号后面的内容】
     * @param filename
     * @return
     */
    @GetMapping("/get1/{filename}")
    public String getPic1(@PathVariable("filename") String filename) {
        String fileUrl = minioUtil.getObjectUrl("java265-info",filename);
        return fileUrl;
    }

    /**
     * 获取图片的路径【不带问号后面的坐标】
     * @param filename
     * @return
     */
    @GetMapping("/get2/{filename}")
    public String getPic2(@PathVariable("filename") String filename) {
        String fileUrl = minioUtil.getObjectUrl("java265-info",filename);
        fileUrl = fileUrl.substring(0, fileUrl.indexOf("?"));
        return fileUrl;
    }

    /**
     * 删除图片【不带路径】 localhost/java265/minio/delete1/lisi.jpg
     * @param filename
     * @return
     */
    @DeleteMapping("/delete1/{filename}")
    public String delete1(@PathVariable("filename") String filename) {
        boolean remove = minioUtil.removeObject("java265-simple",filename);
        return remove ? "删除成功" : "失败";
    }

    /**
     * 删除图片【带路径】 localhost/java265/minio/delete2?filename=aa/lisi.jpg
     * @param filename
     * @return
     */
    @DeleteMapping("/delete2")
    public String delete2(String filename) {
        boolean remove = minioUtil.removeObject("java265-simple",filename);
        return remove ? "删除成功" : "失败";
    }

    /**
     * 批量删除,localhost/java265/minio/delete3?filename=aa.jpg&filename=bb.jpg
     * @param filename
     * @return
     */
    @DeleteMapping("/delete3")
    public String delete3(String... filename) {
        boolean remove = minioUtil.removeObjects("java265-simple",filename);
        return remove ? "删除成功" : "失败";
    }

    @GetMapping("/getBucketObjects")
    public List<Item> getBucketObjects() {
        List<Item> bucketObjects = minioUtil.getBucketObjects("java265-simple");
        return bucketObjects;
    }

    /**
     * 下载图片
     * @param filename
     */
    @GetMapping("/download/{filename}")
    public void downloadPic(@PathVariable("filename") String filename) {
        InputStream is = minioUtil.getObject("java265-simple",filename);

        byte[] buffer = new byte[1024];
        int len = -1;
        try {
            FileOutputStream fos = new FileOutputStream("aa32.jpg");
            while ((len = is.read(buffer)) != -1) {
                fos.write(buffer, 0, len);
            }
            fos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 下载图片
     * @param filename
     */
    @GetMapping("/download2/{filename}")
    public void downloadPic2(@PathVariable("filename") String filename, HttpServletResponse response) {
        minioUtil.getObject("java265-simple",filename, response);
    }
}

第六步:启动项目 测试Controller

版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

本文链接: https://www.Java265.com/JavaFramework/SpringBoot/202305/6382.html

最近发表

热门文章

好文推荐

Java265.com

https://www.java265.com

站长统计|粤ICP备14097017号-3

Powered By Java265.com信息维护小组

使用手机扫描二维码

关注我们看更多资讯

java爱好者