springboot 整合 minio实现文件上传、文件下载

                关于minio服务的安装这里就不过多介绍了,网上都有很多现场的案例,这里主要介绍我在项目中的集成,首先就是引入依赖

            <!-- minio对象存储 -->
            <dependency>
                <groupId>io.minio</groupId>
                <artifactId>minio</artifactId>
                <version>7.1.0</version>
            </dependency>

                yml中配置minio相关配置

minio:
    endpoint: http://127.0.0.1:9000
    accessKey: ***
    secretKey: ***
    bucketName: account-dev
    businessName: 1210Head

               创建minio单例客户端

package com.yl.framework.config;

import io.minio.MinioClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;


/**
 * @author shg
 * @date 2023/1/21 15:42
 * @desc Minio单例客户端
 */
@Slf4j
@Configuration
public class MinioClientSingleton {

    /**
     * Minio服务端地址
     */
    private static String endpoint;

    /**
     * Minio服务端账号
     */
    private static String accessKey;

    /**
     * Minio服务端密码
     */
    private static String secretKey;

    @Value("${minio.endpoint}")
    public void setEndpoint(String endpoint) {
        MinioClientSingleton.endpoint = endpoint;
    }

    @Value("${minio.accessKey}")
    public void setAccessKey(String accessKey) {
        MinioClientSingleton.accessKey = accessKey;
    }

    @Value("${minio.secretKey}")
    public void setSecretKey(String secretKey) {
        MinioClientSingleton.secretKey = secretKey;
    }

    /**
     * Minio客户端
     */
    private static volatile MinioClient minioClient;
    public MinioClientSingleton() {
    }

    /**
     * 获取minio客户端实例
     *
     * @return {@link MinioClient}
     */
    public static MinioClient getMinioClient() {
        if (minioClient == null) {
            synchronized (MinioClientSingleton.class) {
                if (minioClient == null) {
                    minioClient = MinioClient.builder()
                            .endpoint(endpoint)
                            .credentials(accessKey, secretKey)
                            .build();
                    log.info("MinioClientSingleton#getMinioClient,endpoint={},accessKey={},secretKey={}",
                            endpoint, accessKey, secretKey);

                }
            }
        }
        return minioClient;
    }

}

                封装minio工具类:

package com.yl.framework.util;

import com.google.common.collect.Lists;
import com.yl.framework.config.MinioClientSingleton;
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.DeleteObject;
import io.minio.messages.Item;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author shg
 * @date 2023/1/21 15:42
 * @desc Minio客户端工具类
 */
@SuppressWarnings("ALL")
@Slf4j
public class MinioKit {

    /**
     * 判断存储桶是否存在
     *
     * @param bucketName 存储桶名称
     * @return
     */
    @SneakyThrows
    public static boolean bucketExists(String bucketName) {
        boolean found = false;
        try {
            found = MinioClientSingleton.getMinioClient().
                    bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            log.error("MinioKit#bucketExists,查询存储桶异常,bucketName={}", bucketName, e);
            throw new RuntimeException("查询存储桶异常");
        }
        return found;
    }

    /**
     * 创建存储桶
     *
     * @param bucketName 存储桶名称
     * @return
     */
    @SneakyThrows
    public static boolean makeBucket(String bucketName) {
        if (!bucketExists(bucketName)) {
            MinioClientSingleton.getMinioClient().
                    makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
            log.info("MinioKit#makeBucket,存储桶创建成功,bucketName={}", bucketName);
            return true;
        }
        log.info("MinioKit#makeBucket,存储桶已存在,bucketName={}", bucketName);
        return false;
    }

    /**
     * 列出所有的存储桶
     *
     * @return
     */
    @SneakyThrows
    public static List<Bucket> listBuckets() {
        return MinioClientSingleton.getMinioClient().listBuckets();
    }

    /**
     * 列出所有存储桶名称
     *
     * @return
     */
    @SneakyThrows
    public static List<String> listBucketNames() {
        return StreamKit.getList(listBuckets(), Bucket::name);
    }

    /**
     * 删除一个存储桶
     * 注意:只有存储桶为空时才能删除成功
     *
     * @param bucketName 存储桶名称
     */
    @SneakyThrows
    public static boolean removeBucket(String bucketName) {
        // 删除之前先检查存储桶是否存在。
        boolean found = bucketExists(bucketName);
        if (found) {
            Iterable<Result<Item>> myObjects = listObjects(bucketName);
            for (Result<Item> result : myObjects) {
                Item item = result.get();
                // 有对象文件,则删除失败
                if (item.size() > 0) {
                    return false;
                }
            }
            // 删除存储桶,注意,只有存储桶为空时才能删除成功。
            MinioClientSingleton.getMinioClient().removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
            found = bucketExists(bucketName);
            return !found;
        }
        return false;
    }

    /**
     * 列出存储桶中的所有对象名称
     *
     * @param bucketName 存储桶名称
     */
    @SneakyThrows
    public static List<String> listObjectNames(String bucketName) {
        List<String> listObjectNames = new ArrayList<>();
        if (bucketExists(bucketName)) {
            for (Result<Item> result : listObjects(bucketName)) {
                listObjectNames.add(result.get().objectName());
            }
        }
        return listObjectNames;
    }

    /**
     * 列出存储桶中的所有对象(递归查询)
     *
     * @param bucketName 存储桶名称
     */
    @SneakyThrows
    public static Iterable<Result<Item>> listObjects(String bucketName) {
        if (bucketExists(bucketName)) {
            return MinioClientSingleton.getMinioClient().
                    listObjects(ListObjectsArgs.builder().bucket(bucketName).recursive(true).build());
        }
        return Lists.newArrayList();
    }

    /**
     * 删除文件
     *
     * @param bucketName 存储桶名称
     * @param objectName 对象名 (文件夹名+文件名)
     * @return
     */
    @SneakyThrows
    public static boolean removeObject(String bucketName, String objectName) {
        if (bucketExists(bucketName)) {
            MinioClientSingleton.getMinioClient().
                    removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build());
            return true;
        }
        return false;
    }

    /**
     * 批量删除文件
     *
     * @param bucketName  存储桶名称
     * @param objectNames 对象名(文件夹名+文件名)列表
     * @return
     */
    @SneakyThrows
    public static boolean removeObjects(String bucketName, List<String> objectNames) {
        if (bucketExists(bucketName)) {
            // 转换对象
            List<DeleteObject> objects = StreamKit.getList(objectNames, model -> {
                return new DeleteObject(model);
            });

            MinioClientSingleton.getMinioClient().
                    removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(objects).build());
            return true;
        }
        return false;
    }

    /**
     * 以流的形式获取一个文件对象
     *
     * @param bucketName 存储桶名称
     * @param objectName 对象名 (文件夹名+文件名)
     * @return {@link InputStream}
     */
    @SneakyThrows
    public static InputStream getObjectInputStream(String bucketName, String objectName) {
        if (bucketExists(bucketName)) {
            ObjectStat objectStat = MinioClientSingleton.getMinioClient()
                    .statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());
            if (objectStat!=null) {
                // 获取objectName的输入流。
                return MinioClientSingleton.getMinioClient()
                        .getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());
            }
        }
        return null;
    }

    /**
     * 获取某个桶下某个对象的URL
     *
     * @param bucketName 存储桶名称
     * @param objectName 对象名 (文件夹名 + 文件名)
     * @return
     */
    @SneakyThrows
    public static String getBucketObject(String bucketName, String objectName) {
        if (bucketExists(bucketName)) {
            return MinioClientSingleton.getMinioClient().getObjectUrl(bucketName, objectName);
        }
        return null;
    }

    /**
     * 根据文件路径得到预览文件绝对地址
     *
     * @param bucketName 存储桶名称
     * @param objectName 对象名 (文件夹名+文件名)
     * @return
     */
    @SneakyThrows
    public static String getPreviewFileUrl(String bucketName, String objectName) {
        if (bucketExists(bucketName)) {
            return MinioClientSingleton.getMinioClient().getPresignedObjectUrl(
                    GetPresignedObjectUrlArgs.builder()
                            .bucket(bucketName)
                            .object(objectName)
                            .method(Method.GET)
                            .expiry(5, TimeUnit.DAYS)
                            .build());
        }
        return null;
    }

    /**
     * 通过MultipartFile,上传文件
     *
     * @param bucketName 存储桶
     * @param file       文件
     * @param objectName 对象名
     */
    public static void putObject(String bucketName, MultipartFile file, String objectName, String contentType) throws Exception {
        InputStream inputStream = file.getInputStream();

        ObjectWriteResponse objectWriteResponse = MinioClientSingleton.getMinioClient().putObject(
                PutObjectArgs.builder().bucket(bucketName).object(objectName).contentType(contentType)
                        .stream(
                                inputStream, inputStream.available(), -1)
                        .build());
        String url = MinioClientSingleton.getMinioClient().getObjectUrl(bucketName, objectName);	//文件访问路径
    }

    /**
     * 上传本地文件
     *
     * @param bucketName 存储桶
     * @param objectName 对象名称
     * @param fileName   本地文件路径
     */
    public static  ObjectWriteResponse putObject(String bucketName, String objectName, String fileName) throws Exception {
        return MinioClientSingleton.getMinioClient().uploadObject(UploadObjectArgs.builder().bucket(bucketName).object(objectName).filename(fileName).build());
    }

    /**
     * 通过流上传文件
     *
     * @param bucketName  存储桶
     * @param objectName  文件对象
     * @param inputStream 文件流
     */
    public static  ObjectWriteResponse putObjectbyStream(String bucketName, String objectName, InputStream inputStream) throws Exception {
        return MinioClientSingleton.getMinioClient().putObject(
                PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(
                                inputStream, inputStream.available(), -1)
                        .build());
    }

    /**
     * 创建文件夹或目录
     *
     * @param bucketName 存储桶
     * @param objectName 目录路径
     */
    public  ObjectWriteResponse putDirObject(String bucketName, String objectName)
            throws Exception {
        return MinioClientSingleton.getMinioClient().putObject(
                PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(
                                new ByteArrayInputStream(new byte[]{}), 0, -1)
                        .build());
    }

}

        定义文件上传、文件下载统一接口

package com.yl.web.controller.file;

import com.yl.common.core.domain.AjaxResult;
import com.yl.framework.util.MinioKit;
import com.yl.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.util.IOUtils;
import org.springframework.beans.factory.annotation.Value;
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.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.HashMap;

/**
 * minio文件操作相关接口
 *
 * @author shg
 * @date 2022-07-14
 */

@RestController
@Slf4j
@RequestMapping("/file")
public class MinioFileOperateController {
    @Value("${minio.endpoint}")
    private String endpoint;
    @Value("${minio.bucketName}")
    private String bucketName;
    @Value("${minio.businessName}")
    private String businessName;

    @PostMapping("/upload")
    public AjaxResult fileUpload(MultipartFile file) {
        //避免重复,生成新的文件名
        String originalFilename = file.getOriginalFilename();
        String fileType = originalFilename.substring(originalFilename.lastIndexOf("."));
        String fileName = originalFilename.substring(0, originalFilename.indexOf("."));
        LocalDateTime now = LocalDateTime.now();
        String newFileName = fileName + "_" + now.toInstant(ZoneOffset.of("+8")).toEpochMilli() + fileType;

        //生成文件存储path:业务名 + /年/月/日/原文件名_时间搓.文件类型
        String filePath = businessName + "/" + now.getYear() + "/" + String.format("%02d", now.getMonthValue())   + "/" + String.format("%02d", now.getDayOfMonth()) + "/";
        try {
            HashMap<String, String> resultMap = new HashMap<>();
            MinioKit.putObject(bucketName, file,filePath + newFileName, fileType);
            resultMap.put("oldFileName", fileName + "." + fileType);
            resultMap.put("fileName", filePath + newFileName);
            resultMap.put("previewFileUrl", endpoint + "/" + bucketName + "/" + (filePath + newFileName));
            resultMap.put("url", MinioKit.getPreviewFileUrl(bucketName, filePath + newFileName));
            log.info("result: {}", resultMap);
            return AjaxResult.success(resultMap);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("上传失败: "+e.getMessage());
        }
    }

    @GetMapping("/download")
    public void fileDownload(HttpServletResponse response, String name) {
        if (StringUtils.isBlank(name)) {
            return;
        }

        ServletOutputStream ops = null;
        InputStream objectInputStream = MinioKit.getObjectInputStream(bucketName, name);
        try {
            ops = response.getOutputStream();
            IOUtils.copy(objectInputStream,ops);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                ops.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

        后端的整合封装完毕

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
首先,需要引入minio的依赖: ``` <dependency> <groupId>io.minio</groupId> <artifactId>minio</artifactId> <version>8.0.2</version> </dependency> ``` 然后,在application.properties中配置minio的连接信息: ``` minio.url=http://localhost:9000 minio.accessKey=minioadmin minio.secretKey=minioadmin minio.bucketName=test ``` 接着,创建一个MinioService类,用于处理文件下载: ``` @Service public class MinioService { @Value("${minio.url}") private String minioUrl; @Value("${minio.accessKey}") private String accessKey; @Value("${minio.secretKey}") private String secretKey; @Value("${minio.bucketName}") private String bucketName; private final MinioClient minioClient = new MinioClient(minioUrl, accessKey, secretKey); public void upload(MultipartFile file) throws Exception { // 生成文件名 String originalFilename = file.getOriginalFilename(); String fileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf(".")); // 上文件 minioClient.putObject(PutObjectArgs.builder() .bucket(bucketName) .object(fileName) .stream(file.getInputStream(), file.getSize(), -1) .contentType(file.getContentType()) .build()); } public InputStream download(String fileName) throws Exception { // 下载文件 return minioClient.getObject(GetObjectArgs.builder() .bucket(bucketName) .object(fileName) .build()); } } ``` 最后,在Controller中使用MinioService处理上下载请求: ``` @RestController public class MinioController { @Autowired private MinioService minioService; @PostMapping("/upload") public String upload(@RequestParam("file") MultipartFile[] files) { try { for (MultipartFile file : files) { minioService.upload(file); } return "上成功"; } catch (Exception e) { e.printStackTrace(); return "上失败"; } } @GetMapping("/download") public ResponseEntity<InputStreamResource> download(@RequestParam("fileName") String fileName) { try { InputStream inputStream = minioService.download(fileName); InputStreamResource inputStreamResource = new InputStreamResource(inputStream); HttpHeaders headers = new HttpHeaders(); headers.add("Content-Disposition", "attachment; filename=" + fileName); return ResponseEntity.ok().headers(headers).contentLength(inputStream.available()) .contentType(MediaType.parseMediaType("application/octet-stream")).body(inputStreamResource); } catch (Exception e) { e.printStackTrace(); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null); } } } ``` 这样,就可以使用Spring Boot和Minio实现文件批量上了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值