MinIO实现文件上传与下载

发布时间 2023-10-21 17:27:12作者: 安详的苦丁茶

引入依赖

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

 

工具类 MinIoUtils

@Autowired
    SiMinIoProperties minIoProperties;

    private static MinioClient minioClient;


    /**
     * 初始化minio配置
     */
    @PostConstruct
    public void init() {
        try {
            minioClient = new MinioClient(minIoProperties.getEndpoint(), minIoProperties.getAccessKey(), minIoProperties.getSecretKey());
            createBucket(minIoProperties.getBucketName());
        } catch (Exception e) {
            e.printStackTrace();
            log.error("初始化minio配置异常: {}", e.fillInStackTrace());
        }
    }

    /**
     * 判断 bucket是否存在
     *
     * @param bucketName: 桶名
     * @return: boolean
     */
    @SneakyThrows(Exception.class)
    public static boolean bucketExists(String bucketName) {
        return minioClient.bucketExists(bucketName);
    }

    /**
     * 创建 bucket
     *
     * @param bucketName: 桶名
     * @return: void
     */
    @SneakyThrows(Exception.class)
    public static void createBucket(String bucketName) {
        boolean isExist = minioClient.bucketExists(bucketName);
        if (!isExist) {
            minioClient.makeBucket(bucketName);
        }
    }

    /**
     * 获取全部bucket
     *
     * @param :
     * @return: java.util.List<io.minio.messages.Bucket>
     */
    @SneakyThrows(Exception.class)
    public static List<Bucket> getAllBuckets() {
        return minioClient.listBuckets();
    }

    /**
     * 文件上传
     *
     * @param bucketName: 桶名
     * @param fileName:   文件名
     * @param filePath:   文件路径
     * @return: void
     * @date : 2020/8/16 20:53
     */
    @SneakyThrows(Exception.class)
    public static void upload(String bucketName, String fileName, String filePath) {
        minioClient.putObject(bucketName, fileName, filePath, null);
    }

    /**
     * 文件上传
     *
     * @param bucketName: 桶名
     * @param fileName:   文件名
     * @param stream:     文件流
     * @return: java.lang.String : 文件url地址
     */
    @SneakyThrows(Exception.class)
    public static String upload(String bucketName, String fileName, InputStream stream) {
        minioClient.putObject(bucketName, fileName, stream, new PutObjectOptions(stream.available(), -1));
        return getFileUrl(bucketName, fileName);
    }


    /**
     * 上传时指定对应对内容类型
     *
     * @param bucketName  桶名
     * @param folderName  文件夹名
     * @param newFileName 新文件名
     * @param file        文件
     * @return 加密签名的url
     */
    public static String uploadFile(String bucketName, String folderName, String newFileName, MultipartFile file) {
        try {
            //判断桶是否存在
            boolean flag = bucketExists(bucketName);
            if (!flag) {
                createBucket(bucketName);
            }
            //创建文件夹并上传文件
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(folderName + "/" + newFileName)
                    .contentType(ViewContentType.getContentType(file.getOriginalFilename()))
                    .stream(file.getInputStream(), file.getSize(), -1)
                    .build();
            minioClient.putObject(putObjectArgs);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return getFileUrl(bucketName, folderName + newFileName);
    }

    /**
     * 私有上传
     *
     * @param bucketName  桶名
     * @param folderName  文件夹名
     * @param newFileName 新文件名
     * @param file        文件
     * @return
     */
    public static String uploadFilePrivate(String bucketName, String folderName, String newFileName, MultipartFile file) {
        //上传文件
        uploadFile(bucketName, folderName, newFileName, file);
        try {
            //临时签名地址
            return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                    .method(Method.GET)
                    .bucket(bucketName)
                    .object(folderName + "/" + newFileName)
                    .expiry(60)
                    .build());
        } catch (IOException | InvalidKeyException | NoSuchAlgorithmException | ErrorResponseException | ServerException | InsufficientDataException | InvalidResponseException | InternalException | InvalidBucketNameException | InvalidExpiresRangeException | XmlParserException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 文件上传
     *
     * @param bucketName: 桶名
     * @param file:       文件
     * @return: java.lang.String : 文件url地址
     */
    @SneakyThrows(Exception.class)
    public static String upload(String bucketName, MultipartFile file) {
        final InputStream is = file.getInputStream();
        final String fileName = file.getOriginalFilename();
        minioClient.putObject(bucketName, fileName, is, new PutObjectOptions(is.available(), -1));
        is.close();
        return getFileUrl(bucketName, fileName);
    }

    /**
     * 删除文件
     *
     * @param bucketName: 桶名
     * @param url:        访问地址
     * @return: void
     */
    @SneakyThrows(Exception.class)
    public static void deleteFile(String bucketName, String url) {
        String objectName = urlAnalyze(url);
        minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build());
    }

    /**
     * 获取对象(文件)地址
     *
     * @param bucketName 桶名
     * @param objectName 对象名
     * @return 非签名加密地址
     */
    @SneakyThrows(Exception.class)
    public static String getObjectUrl(String bucketName, String objectName) {
        return minioClient.getObjectUrl(bucketName, objectName);
    }


    /**
     * 获取预签名对象Url
     *
     * @param bucketName       桶名
     * @param url              访问地址
     * @param expiresInSeconds 过期时间(秒)
     * @return
     */
    public static String getPreSignedObjectUrl(String bucketName, String url, int expiresInSeconds) {
        try {
            return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                    .method(Method.GET)
                    .bucket(bucketName)
                    .object(urlAnalyze(url))
                    .expiry(expiresInSeconds)
                    .build());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 地址解析
     *
     * @param url 访问地址
     * @return objectName
     */
    public static String urlAnalyze(String url) {
        // 解析URL
        URL parsedUrl;
        try {
            parsedUrl = new URL(URLDecoder.decode(url, "UTF-8"));
        } catch (Exception e) {
            e.printStackTrace();
            return "url转换异常";
        }
        // 提取文件夹名称和对象名称
        String path = parsedUrl.getPath().substring(1);
        String bucketName = "";
        String objectName = "";

        // 如果路径中包含斜杠,则表示存在文件夹
        if (path.contains("/")) {
            bucketName = path.substring(0, path.indexOf("/"));
            objectName = path.substring(path.indexOf("/") + 1);
        } else {
            objectName = path;
        }
        //System.out.println("Bucket名称:" + bucketName);
        //System.out.println("对象名称:" + objectName);
        return objectName;
    }


    /**
     * 获取存储桶中所有对象的名称
     *
     * @param bucketName
     * @return
     * @throws Exception
     */
    public static List<String> listObjects(String bucketName) throws Exception {
        ListObjectsArgs args = ListObjectsArgs.builder()
                .bucket(bucketName)
                .build();
        Iterable<Result<Item>> objects = minioClient.listObjects(args);

        List<String> objectNames = new ArrayList<>();
        for (Result<Item> result : objects) {
            objectNames.add(result.get().objectName());
        }
        return objectNames;
    }


    /**
     * 下载文件
     *
     * @param bucketName: 桶名
     * @param url:        文件访问地址
     * @param response:
     * @return: void
     */
    @SneakyThrows(Exception.class)
    public static void download(String bucketName, String url, HttpServletResponse response) {
        String objectName = urlAnalyze(url);
        // 获取对象的元数据
        final ObjectStat stat = minioClient.statObject(bucketName, urlAnalyze(url));
        response.setContentType(stat.contentType());
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(objectName, "UTF-8"));
        InputStream is = minioClient.getObject(bucketName, objectName);
        is.close();
    }

    /**
     * 获取minio文件的下载地址
     *
     * @param bucketName: 桶名
     * @param objectName: 文件名
     * @return: java.lang.String
     */
    @SneakyThrows(Exception.class)
    public static String getFileUrl(String bucketName, String objectName) {
        return minioClient.presignedGetObject(bucketName, objectName);
    }

    /**
     * @param bucketName 桶名
     * @param folderName 文件夹名称
     * @param file       文件
     * @throws InvalidKeyException
     * @throws ErrorResponseException
     * @throws IllegalArgumentException
     * @throws InsufficientDataException
     * @throws InternalException
     * @throws InvalidBucketNameException
     * @throws InvalidResponseException
     * @throws NoSuchAlgorithmException
     * @throws XmlParserException
     * @throws IOException
     * @throws ServerException
     */
    public static void putObject(String bucketName, String folderName, String newFileName, MultipartFile file)
            throws InvalidKeyException, ErrorResponseException, IllegalArgumentException, InsufficientDataException,
            InternalException, InvalidBucketNameException, InvalidResponseException, NoSuchAlgorithmException,
            XmlParserException, IOException, ServerException {
        //判断桶是否存在
        boolean flag = bucketExists(bucketName);
        if (flag) {
            //王文建文件夹并上传文件
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(folderName + "/" + newFileName)
                    .contentType(ViewContentType.getContentType(file.getOriginalFilename()))
                    .stream(file.getInputStream(), file.getSize(), -1)
                    .build();
            minioClient.putObject(putObjectArgs);
        }
    }


    public ObjectStat statObject(String bucketName, String objectName)
            throws InvalidKeyException, ErrorResponseException, IllegalArgumentException, InsufficientDataException,
            InternalException, InvalidBucketNameException, InvalidResponseException, NoSuchAlgorithmException,
            XmlParserException, IOException {
        boolean flag = bucketExists(bucketName);
        if (flag) {
            ObjectStat statObject = null;
            try {
                statObject = minioClient.statObject(bucketName, objectName);
            } catch (ServerException e) {
                e.printStackTrace();
            }
            return statObject;
        }
        return null;
    }


    /**
     * 创建文件夹
     *
     * @param bucketName
     * @param folderName
     * @return
     * @throws IOException
     * @throws InvalidKeyException
     * @throws InvalidResponseException
     * @throws InsufficientDataException
     * @throws NoSuchAlgorithmException
     * @throws ServerException
     * @throws InternalException
     * @throws XmlParserException
     * @throws InvalidBucketNameException
     * @throws ErrorResponseException
     */
    public static void createFolder(String bucketName, String folderName) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException {
        // 创建虚拟文件夹
        String objectName = folderName + "/";

        // 使用空的输入流创建对象
        minioClient.putObject(PutObjectArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .stream(new ByteArrayInputStream(new byte[0]), 0, -1)
                .build());
    }

支持上传文件、下载、访问文件、预签名底子(有效期地址)、对桶的操作

 

配置类SiMinIoProperties

@Data
@Configuration
@ConfigurationProperties(prefix = "minio")
public class SiMinIoProperties {

    /**
     * minio地址+端口号
     */
    private String endpoint;

    /**
     * minio用户名
     */
    private String accessKey;

    /**
     * minio密码
     */
    private String secretKey;

    /**
     * 文件桶的名称
     */
    private String bucketName;

    /**
     * 访问图片有效时间(单位:秒)
     */
    private Integer expiresInSeconds;

}

这里配置在yml配置文件上

注意:minio的用户名和密码,也就是秘钥,在minio控制台获取

桶要设置访问权限为public,不然无法访问! 

 

枚举类ViewContentType

DEFAULT("default","application/octet-stream"),
    JPG("jpg", "image/jpeg"),
    TIFF("tiff", "image/tiff"),
    GIF("gif", "image/gif"),
    JFIF("jfif", "image/jpeg"),
    PNG("png", "image/png"),
    TIF("tif", "image/tiff"),
    ICO("ico", "image/x-icon"),
    JPEG("jpeg", "image/jpeg"),
    WBMP("wbmp", "image/vnd.wap.wbmp"),
    FAX("fax", "image/fax"),
    NET("net", "image/pnetvue"),
    JPE("jpe", "image/jpeg"),
    RP("rp", "image/vnd.rn-realpix"),
    MAP("mp4", "video/mp4"),
    MPEG("mpeg", "video/mpeg"),
    AVI("avi", "video/avi"),
    PDF("pdf", "application/pdf")
    ;

    private String prefix;

    private String type;

    public static String getContentType(String prefix){
        if(StringUtils.isEmpty(prefix)){
            return DEFAULT.getType();
        }
        prefix = prefix.substring(prefix.lastIndexOf(".") + 1);
        for (ViewContentType value : ViewContentType.values()) {
            if(prefix.equalsIgnoreCase(value.getPrefix())){
                return value.getType();
            }
        }
        return DEFAULT.getType();
    }

    ViewContentType(String prefix, String type) {
        this.prefix = prefix;
        this.type = type;
    }

    public String getPrefix() {
        return prefix;
    }

    public String getType() {
        return type;
    }

 

有其它问题请下方留言