Typora自动上传图片,springboot集成Minio做私有化图床

Typora设置最简单的自动上传和手动上传图片并回显效果

在这里插入图片描述

在Typora里面设置一下插入图片时就能自动上传到Minio的服务器上了,这样同一个局域网的同学打开也能正常查看笔记内容了;

@echo off
set currentDate=%date:~0,4%-%date:~5,2%-%date:~8,2%
curl -X POST -F "folderName=%currentDate%" -F "file=@%~1" http://{IP}:{PORT}/minio/upload

bat文件里面的脚本说明:

1.通过curl访问服务接口:http://{IP}:{PORT}/minio/upload
2.传递参数:
	第一个参数为当前日期如:2023-11-07;作为minio服务上的目录
	第二个参数为需要上传的图片,即完整的图片路径

这样复制粘贴的图片就会按天自动归类到服务器上了如下面这样:

在这里插入图片描述

Minio部署这里就不讲了,就一个文件启动起来就行;

springboot集成Minio

依赖

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

核心实现类

package com.ygsoft.jt.teng.cp.minio.service;

import com.ygsoft.jt.teng.cp.minio.config.MinioConfig;
import com.ygsoft.jt.teng.cp.minio.constant.MinioConstant;
import com.ygsoft.jt.teng.cp.minio.entity.MultiPartUploadInfo;
import com.ygsoft.jt.teng.cp.minio.enums.PolicyType;
import com.ygsoft.jt.teng.cp.minio.service.client.ExtendMinioAsyncClient;
import com.ygsoft.jt.teng.cp.minio.utils.MinioUtil;
import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import io.minio.messages.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author hhong <br>
 * @version 1.0.0 2023/11/3 9:30 <br>
 * @since JDK 1.8.0
 */
@Service
public class MinioService {
    private static final Logger LOGGER = LoggerFactory.getLogger(MinioService.class);
    private final MinioConfig minioConfig;

    private final ExtendMinioAsyncClient minioAsyncClient;

    private final MinioClient minioClient;

    public MinioService(MinioConfig minioConfig, ExtendMinioAsyncClient minioAsyncClient, MinioClient minioClient) {
        this.minioConfig = minioConfig;
        this.minioAsyncClient = minioAsyncClient;
        this.minioClient = minioClient;
    }

    /**
     * 查看指定bucket是否存在
     *
     * @param bucketName bucket名称
     * @return
     */
    public boolean bucketExists(String bucketName) throws MinioException {
        try {
            return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        } catch (ErrorResponseException | IOException | InsufficientDataException
                 | InternalException | InvalidKeyException | InvalidResponseException
                 | NoSuchAlgorithmException | XmlParserException | ServerException e) {
            throw new MinioException(e.getMessage());
        }
    }

    /**
     * 创建一个bucket
     *
     * @param bucketName bucket名称
     * @return
     */
    public boolean createBucket(String bucketName) throws MinioException {
        try {
            if (!bucketExists(bucketName)) {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
            }
            return true;
        } catch (ErrorResponseException | IOException | InsufficientDataException
                 | InternalException | InvalidKeyException | InvalidResponseException
                 | NoSuchAlgorithmException | XmlParserException | ServerException e) {
            throw new MinioException(e.getMessage());
        }
    }
    public void createFolder(String bucketName,String folderName) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        minioClient.putObject(
                PutObjectArgs.builder()
                        .bucket(bucketName)
                        .object(folderName + MinioConstant.URI_DELIMITER)
                        .stream(new ByteArrayInputStream(new byte[0]),0,-1)
                        .build()
        );
    }
    /**
     * 创建一个bucket,并指定访问策略
     *
     * @param bucketName bucket名称
     * @param policyType 访问策略
     * @return
     */
    public boolean createBucket(String bucketName, PolicyType policyType) throws MinioException {
        try {
            if (this.createBucket(bucketName)) {
                minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucketName).config(PolicyType.getPolicy(policyType, bucketName)).build());
            }
            return true;
        } catch (ErrorResponseException | IOException | InsufficientDataException
                 | InternalException | InvalidKeyException | InvalidResponseException
                 | NoSuchAlgorithmException | XmlParserException | ServerException e) {
            throw new MinioException(e.getMessage());
        }
    }

    /**
     * 创建一个bucket,并指定访问策略,默认三种不满足时,自定义可调用此方法
     *
     * @param bucketName bucket名称
     * @param policy     访问策略
     * @return
     */
    public boolean createBucket(String bucketName, String policy) throws MinioException {
        try {
            if (this.createBucket(bucketName)) {
                minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucketName).config(policy).build());
            }
            return true;
        } catch (ErrorResponseException | IOException | InsufficientDataException
                 | InternalException | InvalidKeyException | InvalidResponseException
                 | NoSuchAlgorithmException | XmlParserException | ServerException e) {
            throw new MinioException(e.getMessage());
        }
    }

    /**
     * 指定访问策略
     *
     * @param bucketName bucket名称
     * @param policyType 访问策略
     * @return
     */
    public boolean setBucketPolicy(String bucketName, PolicyType policyType) throws MinioException {
        try {
            if (!bucketExists(bucketName)) {
                throw new MinioException(bucketName + " bucket does not exist.");
            }
            minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucketName).config(PolicyType.getPolicy(policyType, bucketName)).build());
            return true;
        } catch (ErrorResponseException | IOException | InsufficientDataException
                 | InternalException | InvalidKeyException | InvalidResponseException
                 | NoSuchAlgorithmException | XmlParserException | ServerException e) {
            throw new MinioException(e.getMessage());
        }
    }

    /**
     * 指定访问策略,默认三种不满足时,自定义可调用此方法
     *
     * @param bucketName bucket名称
     * @param policy     访问策略
     * @return
     */
    public boolean setBucketPolicy(String bucketName, String policy) throws MinioException {
        try {
            if (!bucketExists(bucketName)) {
                throw new MinioException(bucketName + " bucket does not exist.");
            }
            minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucketName).config(policy).build());
            return true;
        } catch (ErrorResponseException | IOException | InsufficientDataException
                 | InternalException | InvalidKeyException | InvalidResponseException
                 | NoSuchAlgorithmException | XmlParserException | ServerException e) {
            throw new MinioException(e.getMessage());
        }
    }

    /**
     * 获得所有bucket
     *
     * @return
     */
    public List<Bucket> listBuckets() throws MinioException {
        try {
            return minioClient.listBuckets();
        } catch (ErrorResponseException | IOException | InsufficientDataException
                 | InternalException | InvalidKeyException | InvalidResponseException
                 | NoSuchAlgorithmException | XmlParserException | ServerException e) {
            throw new MinioException(e.getMessage());
        }
    }

    /**
     * 获得指定bucket
     *
     * @param bucketName bucket名称
     * @return
     */
    public Optional<Bucket> getBucket(String bucketName) throws MinioException {
        return listBuckets().stream().filter(item -> item.name().equals(bucketName)).findFirst();
    }

    /**
     * 删除一个bucket
     *
     * @param bucketName bucket名称
     * @return
     */
    public boolean removeBucket(String bucketName) throws MinioException {
        try {
            if (bucketExists(bucketName)) {
                minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
            }
            return true;
        } catch (ErrorResponseException | IOException | InsufficientDataException
                 | InternalException | InvalidKeyException | InvalidResponseException
                 | NoSuchAlgorithmException | XmlParserException | ServerException e) {
            throw new MinioException(e.getMessage());
        }
    }

    /**
     * 遍历默认 bucketName 下文件夹名称
     *
     * @return
     */
    public List<Item> listObjects() throws MinioException {
        return listObjects(getBucketName());
    }

    /**
     * 遍历指定 bucketName 下文件夹名称
     *
     * @param bucketName bucket名称
     * @return
     */
    public List<Item> listObjects(String bucketName) throws MinioException {
        return listObjects(bucketName, false);
    }

    /**
     * 遍历文件
     *
     * @param bucketName bucket名称
     * @param recursive  是否递归查询,是,则会返回文件全路径,否,则返回第一级文件夹
     * @return
     */
    public List<Item> listObjects(String bucketName, boolean recursive) throws MinioException {
        return listObjects(bucketName, null, recursive);
    }

    /**
     * 遍历文件
     *
     * @param bucketName bucket名称
     * @param prefix     前缀,包括路径
     * @param recursive  是否递归查询
     * @return
     */
    public List<Item> listObjects(String bucketName, String prefix, boolean recursive) throws MinioException {
        List<Item> objectList = new ArrayList<>();
        Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).prefix(prefix).recursive(recursive).build());
        for (Result<Item> itemResult : results) {
            try {
                objectList.add(itemResult.get());
            } catch (ErrorResponseException | IOException | InsufficientDataException
                     | InternalException | InvalidKeyException | InvalidResponseException
                     | NoSuchAlgorithmException | XmlParserException | ServerException e) {
                throw new MinioException(e.getMessage());
            }
        }
        return objectList;
    }

    /**
     * 获得指定文件 文件流
     *
     * @param objectName
     * @return
     */
    public InputStream getObject(String objectName) throws MinioException {
        return getObject(getBucketName(), objectName);
    }

    /**
     * 获得指定文件 文件流
     *
     * @param bucketName
     * @param objectName
     * @return
     */
    public InputStream getObject(String bucketName, String objectName) throws MinioException {
        InputStream inputStream;
        try {
            inputStream = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(MinioUtil.getObjectName(objectName)).build());
        } catch (ErrorResponseException | IOException | InsufficientDataException
                 | InternalException | InvalidKeyException | InvalidResponseException
                 | NoSuchAlgorithmException | XmlParserException | ServerException e) {
            throw new MinioException(e.getMessage());
        }
        return inputStream;
    }

    /**
     * 获得指定文件 文件流
     *
     * @param bucketName
     * @param objectName
     * @param versionId
     * @return
     */
    public InputStream getObject(String bucketName, String objectName, String versionId) throws MinioException {
        InputStream inputStream;
        try {
            inputStream = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(MinioUtil.getObjectName(objectName)).versionId(versionId).build());
        } catch (ErrorResponseException | IOException | InsufficientDataException
                 | InternalException | InvalidKeyException | InvalidResponseException
                 | NoSuchAlgorithmException | XmlParserException | ServerException e) {
            throw new MinioException(e.getMessage());
        }
        return inputStream;
    }

    /**
     * 获得指定文件 文件流
     *
     * @param bucketName
     * @param objectName
     * @param length
     * @param offset
     * @return
     */
    public InputStream getObject(String bucketName, String objectName, long length, Long offset) throws MinioException {
        InputStream inputStream;
        try {
            inputStream = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(MinioUtil.getObjectName(objectName)).length(length).offset(offset).build());
        } catch (ErrorResponseException | IOException | InsufficientDataException
                 | InternalException | InvalidKeyException | InvalidResponseException
                 | NoSuchAlgorithmException | XmlParserException | ServerException e) {
            throw new MinioException(e.getMessage());
        }
        return inputStream;
    }

    /**
     * 获得外链,过期时间默认7天
     *
     * @param objectName 文件
     * @return
     */
    public String getObjectUrl(String objectName) throws MinioException {
        return getObjectUrl(getBucketName(), objectName);
    }

    /**
     * 获得外链,过期时间默认7天
     *
     * @param bucketName bucket 名称
     * @param objectName 文件
     * @return
     */
    public String getObjectUrl(String bucketName, String objectName) throws MinioException {
        return getObjectUrl(bucketName, objectName, false);
    }

    /**
     * 获得外链,过期时间默认7天
     *
     * @param bucketName     bucket 名称
     * @param objectName     文件
     * @param replaceAddress 是否替换访问域名
     * @return
     */
    public String getObjectUrl(String bucketName, String objectName, boolean replaceAddress) throws MinioException {
        return getObjectUrl(bucketName, objectName, replaceAddress, GetPresignedObjectUrlArgs.DEFAULT_EXPIRY_TIME);
    }

    /**
     * 获得外链
     *
     * @param bucketName     bucket 名称
     * @param objectName     文件
     * @param replaceAddress 是否替换访问域名
     * @param expires        过期时间,单位秒
     * @return
     */
    public String getObjectUrl(String bucketName, String objectName, boolean replaceAddress, Integer expires) throws MinioException {
        try {
            String objectUrl;
            // expires 设置为-1时表示获取永久地址
            if (expires == -1) {
                objectUrl = minioConfig.getEndpoint()+MinioConstant.URI_DELIMITER+bucketName+MinioConstant.URI_DELIMITER+objectName;
            } else {
                objectUrl = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(MinioUtil.getObjectName(objectName)).expiry(expires).method(Method.GET).build());
            }
            //String objectUrl = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(MinioUtil.getObjectName(objectName)).expiry(expires).method(Method.GET).build());
            return replaceAddress && minioConfig.getAddress() != null ? objectUrl.replace(minioConfig.getEndpoint(), minioConfig.getAddress()) : objectUrl;
        } catch (ErrorResponseException | IOException | InsufficientDataException
                 | InternalException | InvalidKeyException | InvalidResponseException
                 | NoSuchAlgorithmException | XmlParserException | ServerException e) {
            throw new MinioException(e.getMessage());
        }
    }

    /**
     * 上传文件
     *
     * @param objectName 文件名称
     * @param stream     文件流
     * @return
     */
    public ObjectWriteResponse putObject(String objectName, InputStream stream) throws MinioException {
        return putObject(getBucketName(), objectName, stream);
    }

    /**
     * 上传文件
     *
     * @param bucketName bucket名称
     * @param objectName 文件名称,如:2021/11/28/test.zip
     * @param stream     文件流
     * @return
     */
    public ObjectWriteResponse putObject(String bucketName, String objectName, InputStream stream) throws MinioException {
        return putObject(bucketName, objectName, null, stream);
    }

    /**
     * 上传文件
     *
     * @param bucketName  bucket名称
     * @param objectName  文件名称,如:2021/11/28/test.zip
     * @param contentType 文件类型
     * @param stream      文件流
     * @return
     */
    public ObjectWriteResponse putObject(String bucketName, String objectName, String contentType,
                                         InputStream stream) throws MinioException {
        try {
            return putObject(bucketName, objectName, contentType, stream, stream.available(), ObjectWriteArgs.MIN_MULTIPART_SIZE);
        } catch (IOException e) {
            throw new MinioException(e.getMessage());
        }
    }

    /**
     * 上传文件
     *
     * @param bucketName  bucket名称
     * @param objectName  文件名称,如:2021/11/28/test.zip
     * @param contentType 文件类型
     * @param stream      文件流
     * @param objectSize  文件大小
     * @return
     */
    public ObjectWriteResponse putObject(String bucketName, String objectName, String contentType,
                                         InputStream stream, long objectSize) throws MinioException {
        return putObject(bucketName, objectName, contentType, stream, objectSize, -1);
    }

    /**
     * 上传文件
     *
     * @param bucketName  bucket名称
     * @param objectName  文件名称,如:2021/11/28/test.zip
     * @param contentType 文件类型
     * @param stream      文件流
     * @param objectSize  文件大小
     * @param partSize    分片大小
     * @return
     */
    public ObjectWriteResponse putObject(String bucketName, String objectName, String contentType,
                                         InputStream stream, long objectSize, long partSize) throws MinioException {
        try {
            return minioClient.putObject(PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(MinioUtil.getObjectName(objectName))
                    .stream(stream, objectSize, partSize)
                    .contentType(MinioUtil.getContentType(contentType))
                    .build());
        } catch (ErrorResponseException | IOException | InsufficientDataException
                 | InternalException | InvalidKeyException | InvalidResponseException
                 | NoSuchAlgorithmException | XmlParserException | ServerException e) {
            throw new MinioException(e.getMessage());
        }
    }

    /**
     * 单个删除
     *
     * @param objectName
     * @return
     */
    public boolean removeObject(String objectName) throws MinioException {
        return removeObject(getBucketName(), objectName);
    }

    /**
     * 单个删除
     *
     * @param bucketName
     * @param objectName
     * @return
     */
    public boolean removeObject(String bucketName, String objectName) throws MinioException {
        try {
            minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(MinioUtil.getObjectName(objectName)).build());
            return true;
        } catch (ErrorResponseException | IOException | InsufficientDataException
                 | InternalException | InvalidKeyException | InvalidResponseException
                 | NoSuchAlgorithmException | XmlParserException | ServerException e) {
            throw new MinioException(e.getMessage());
        }
    }

    /**
     * 批量删除
     *
     * @param bucketName
     * @param objectNames
     * @return
     */
    public List<String> removeObjects(String bucketName, Collection<String> objectNames) throws MinioException {
        List<DeleteObject> objects = objectNames.stream().map(MinioUtil::getObjectName).map(DeleteObject::new).collect(Collectors.toList());
        Iterable<Result<DeleteError>> results = minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(objects).build());
        List<String> errorDeleteObjects = new ArrayList<>();
        try {
            for (Result<DeleteError> result : results) {
                errorDeleteObjects.add(result.get().objectName());
                LOGGER.error(String.format("Error in deleting object %s:%s, code=%s, message=%s",
                        bucketName, result.get().objectName(), result.get().code(), result.get().message()));
            }
        } catch (ErrorResponseException | IOException | InsufficientDataException
                 | InternalException | InvalidKeyException | InvalidResponseException
                 | NoSuchAlgorithmException | XmlParserException | ServerException e) {
            throw new MinioException(e.getMessage());
        }
        return errorDeleteObjects;
    }

    /**
     * 获取上传临时签名
     *
     * @param fileName
     * @return
     * @throws MinioException
     */
    public Map<String, String> getPresignedPostFormData(String fileName) throws MinioException {
        return getPresignedPostFormData(getBucketName(), fileName);
    }

    /**
     * 获取上传临时签名
     *
     * @param bucketName
     * @param fileName
     * @return
     * @throws MinioException
     */
    public Map<String, String> getPresignedPostFormData(String bucketName, String fileName) throws MinioException {
        return getPresignedPostFormData(bucketName, fileName, ZonedDateTime.now().plusMinutes(10));
    }

    /**
     * 获取上传临时签名
     *
     * @param bucketName
     * @param fileName
     * @param time       默认10分钟以内有效
     * @return
     * @throws MinioException
     */
    public Map<String, String> getPresignedPostFormData(String bucketName, String fileName, ZonedDateTime time) throws MinioException {
        return getPresignedPostFormData(bucketName, null, fileName, time);
    }

    /**
     * 获取上传临时签名
     *
     * @param bucketName
     * @param path       文件保存路径,如:test/file
     * @param fileName
     * @return
     * @throws MinioException
     */
    public Map<String, String> getPresignedPostFormData(String bucketName, String path, String fileName) throws MinioException {
        return getPresignedPostFormData(bucketName, path, fileName, ZonedDateTime.now().plusMinutes(10));
    }

    /**
     * 获取上传临时签名
     *
     * @param bucketName
     * @param path       文件保存路径,如:test/file
     * @param fileName
     * @param time
     * @return
     * @throws MinioException
     */
    public Map<String, String> getPresignedPostFormData(String bucketName, String path, String fileName, ZonedDateTime time) throws MinioException {
        PostPolicy postPolicy = new PostPolicy(bucketName, time);
        String key = MinioConstant.URI_DELIMITER + MinioUtil.getPath(path) + fileName;
        postPolicy.addEqualsCondition("key", key);
        try {
            Map<String, String> map = minioClient.getPresignedPostFormData(postPolicy);
            HashMap<String, String> map1 = new HashMap<>();
            map.forEach((k, v) -> map1.put(k.replace("-", ""), v));
            map1.put("key", key);
            map1.put("host", minioConfig.getEndpoint() + MinioConstant.URI_DELIMITER + bucketName);
            return map1;
        } catch (ErrorResponseException | IOException | InsufficientDataException
                 | InternalException | InvalidKeyException | InvalidResponseException
                 | NoSuchAlgorithmException | XmlParserException | ServerException e) {
            throw new MinioException(e.getMessage());
        }
    }

    /**
     * 获取上传文件的url
     *
     * @param objectName
     * @return
     * @throws MinioException
     */
    public String getPresignedObjectPutUrl(String objectName) throws MinioException {
        return getPresignedObjectPutUrl(getBucketName(), objectName);
    }

    /**
     * 获取上传文件的url
     *
     * @param bucketName
     * @param objectName
     * @return
     * @throws MinioException
     */
    public String getPresignedObjectPutUrl(String bucketName, String objectName) throws MinioException {
        return getPresignedObjectPutUrl(bucketName, null, objectName);
    }

    /**
     * 获取上传文件的url
     *
     * @param bucketName
     * @param path
     * @param objectName
     * @return
     * @throws MinioException
     */
    public String getPresignedObjectPutUrl(String bucketName, String path, String objectName) throws MinioException {
        return getPresignedObjectPutUrl(bucketName, path, objectName, 5);
    }

    /**
     * 获取上传文件的url
     *
     * @param bucketName
     * @param path
     * @param objectName
     * @return
     * @throws MinioException
     */
    public String getPresignedObjectPutUrl(String bucketName, String path, String objectName, Integer time) throws MinioException {
        return getPresignedObjectPutUrl(bucketName, path, objectName, time, TimeUnit.MINUTES);
    }

    /**
     * 获取上传文件的url
     *
     * @param bucketName
     * @param path
     * @param objectName
     * @param time
     * @param timeUnit
     * @return
     * @throws MinioException
     */
    public String getPresignedObjectPutUrl(String bucketName, String path, String objectName, Integer time, TimeUnit timeUnit) throws MinioException {
        try {
            objectName = (StringUtils.hasText(path) ? MinioUtil.getPath(path) : "") + MinioUtil.getObjectName(objectName);
            return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                    .method(Method.PUT)
                    .bucket(bucketName)
                    .object(objectName)
                    .expiry(time, timeUnit).build());
        } catch (ErrorResponseException | IOException | InsufficientDataException
                 | InternalException | InvalidKeyException | InvalidResponseException
                 | NoSuchAlgorithmException | XmlParserException | ServerException e) {
            throw new MinioException(e.getMessage());
        }
    }

    /**
     * 获得分片上传的地址信息
     *
     * @param objectName
     * @param partSize
     * @return
     * @throws MinioException
     */
    public MultiPartUploadInfo getPresignedMultipartUploadUrls(String objectName, Integer partSize) throws MinioException {
        return getPresignedMultipartUploadUrls(getBucketName(), objectName, partSize);
    }

    /**
     * 获得分片上传的地址信息
     *
     * @param objectName
     * @param partSize
     * @return
     * @throws MinioException
     */
    public MultiPartUploadInfo getPresignedMultipartUploadUrls(String objectName, Integer partSize, String contentType) throws MinioException {
        return getPresignedMultipartUploadUrls(getBucketName(), objectName, partSize, contentType);
    }

    /**
     * 获得分片上传的地址信息
     *
     * @param bucketName
     * @param objectName
     * @param partSize
     * @return
     * @throws MinioException
     */
    public MultiPartUploadInfo getPresignedMultipartUploadUrls(String bucketName, String objectName, Integer partSize) throws MinioException {
        return getPresignedMultipartUploadUrls(bucketName, null, objectName, partSize);
    }

    /**
     * 获得分片上传的地址信息
     *
     * @param bucketName
     * @param objectName
     * @param partSize
     * @param contentType
     * @return
     * @throws MinioException
     */
    public MultiPartUploadInfo getPresignedMultipartUploadUrls(String bucketName, String objectName, Integer partSize, String contentType) throws MinioException {
        return getPresignedMultipartUploadUrls(bucketName, null, objectName, partSize, contentType);
    }

    /**
     * 获得分片上传的地址信息
     *
     * @param bucketName
     * @param path
     * @param objectName
     * @param partSize
     * @return
     * @throws MinioException
     */
    public MultiPartUploadInfo getPresignedMultipartUploadUrls(String bucketName, String path, String objectName, Integer partSize) throws MinioException {
        return getPresignedMultipartUploadUrls(bucketName, path, objectName, partSize, null);
    }

    /**
     * 获得分片上传的地址信息
     *
     * @param bucketName
     * @param path
     * @param objectName
     * @param partSize
     * @param contentType
     * @return
     * @throws MinioException
     */
    public MultiPartUploadInfo getPresignedMultipartUploadUrls(String bucketName, String path, String objectName, Integer partSize, String contentType) throws MinioException {
        return getPresignedMultipartUploadUrls(bucketName, path, objectName, partSize, contentType, 10);
    }

    /**
     * 获得分片上传的地址信息
     *
     * @param bucketName
     * @param path
     * @param objectName
     * @param partSize
     * @param contentType
     * @param time
     * @return
     * @throws MinioException
     */
    public MultiPartUploadInfo getPresignedMultipartUploadUrls(String bucketName, String path, String objectName, Integer partSize, String contentType, Integer time) throws MinioException {
        return getPresignedMultipartUploadUrls(bucketName, path, objectName, partSize, contentType, time, TimeUnit.MINUTES);
    }

    /**
     * 获得分片上传的地址信息
     *
     * @param bucketName
     * @param path
     * @param objectName
     * @param partSize
     * @param contentType
     * @param time
     * @param timeUnit
     * @return
     * @throws MinioException
     */
    public MultiPartUploadInfo getPresignedMultipartUploadUrls(String bucketName, String path, String objectName, Integer partSize, String contentType, Integer time, TimeUnit timeUnit) throws MinioException {
        String uploadId = "";
        List<String> partUrlList = new ArrayList<>();
        try {
            objectName = (StringUtils.hasText(path) ? MinioUtil.getPath(path) : "") + MinioUtil.getObjectName(objectName);
            InitiateMultipartUploadResult uploadResponse = this.initMultiPartUpload(bucketName, objectName, contentType);
            uploadId = uploadResponse.uploadId();
            Map<String, String> paramsMap = new HashMap<>(2);
            paramsMap.put("uploadId", uploadId);
            for (int i = 1; i <= partSize; i++) {
                paramsMap.put("partNumber", String.valueOf(i));
                // 获取上传 url
                String uploadUrl = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                        // 注意此处指定请求方法为 PUT,前端需对应,否则会报 `SignatureDoesNotMatch` 错误
                        .method(Method.PUT)
                        .bucket(bucketName)
                        .object(objectName)
                        // 指定上传连接有效期
                        .expiry(time, timeUnit)
                        .extraQueryParams(paramsMap).build());
                partUrlList.add(uploadUrl);
            }
        } catch (IOException | InsufficientDataException | InternalException | InvalidKeyException |
                 NoSuchAlgorithmException | XmlParserException e) {
            throw new MinioException(e.getMessage());
        }

        return MultiPartUploadInfo.builder()
                .uploadId(uploadId)
                .fileName(objectName)
                .expiryTime(MinioUtil.getLocalDateTime(time, timeUnit))
                .uploadUrls(partUrlList)
                .build();
    }

    /**
     * 根据分片partNumber获取前端分片上传预签名urls
     *
     * @param uploadId    上传标识,同一个文件,需保证一样,通过 initMultiPartUpload 方法获取
     * @param objectName  文件名称,如:2021/11/28/test.zip
     * @param partNumbers 分片partNumber集合
     * @return
     */
    public MultiPartUploadInfo getPresignedMultipartUploadUrlsByPartNumbers(String uploadId, String objectName, List<Integer> partNumbers) throws MinioException {
        return getPresignedMultipartUploadUrlsByPartNumbers(uploadId, getBucketName(), objectName, partNumbers);
    }

    /**
     * 根据分片partNumber获取前端分片上传预签名urls
     *
     * @param uploadId    上传标识,同一个文件,需保证一样,通过 initMultiPartUpload 方法获取
     * @param bucketName  bucketName
     * @param objectName  文件名称,如:2021/11/28/test.zip
     * @param partNumbers 分片partNumber集合
     * @return
     */
    public MultiPartUploadInfo getPresignedMultipartUploadUrlsByPartNumbers(String uploadId, String bucketName, String objectName, List<Integer> partNumbers) throws MinioException {
        return getPresignedMultipartUploadUrlsByPartNumbers(uploadId, bucketName, null, objectName, partNumbers);
    }

    /**
     * 根据分片partNumber获取前端分片上传预签名urls
     *
     * @param uploadId    上传标识,同一个文件,需保证一样,通过 initMultiPartUpload 方法获取
     * @param bucketName  bucketName
     * @param objectName  文件名称,如:2021/11/28/test.zip
     * @param partNumbers 分片partNumber集合
     * @return
     */
    public MultiPartUploadInfo getPresignedMultipartUploadUrlsByPartNumbers(String uploadId, String bucketName, String path, String objectName, List<Integer> partNumbers) throws MinioException {
        return getPresignedMultipartUploadUrlsByPartNumbers(uploadId, bucketName, path, objectName, partNumbers, 10);
    }

    /**
     * 根据分片partNumber获取前端分片上传预签名urls
     *
     * @param uploadId    上传标识,同一个文件,需保证一样,通过 initMultiPartUpload 方法获取
     * @param bucketName  bucketName
     * @param objectName  文件名称,如:2021/11/28/test.zip
     * @param partNumbers 分片partNumber集合
     * @param time        过期时间,默认10分钟
     * @return
     */
    public MultiPartUploadInfo getPresignedMultipartUploadUrlsByPartNumbers(String uploadId, String bucketName, String path, String objectName, List<Integer> partNumbers, Integer time) throws MinioException {
        return getPresignedMultipartUploadUrlsByPartNumbers(uploadId, bucketName, path, objectName, partNumbers, time, TimeUnit.MINUTES);
    }

    /**
     * 根据分片partNumber获取前端分片上传预签名urls
     *
     * @param uploadId    上传标识,同一个文件,需保证一样,通过 initMultiPartUpload 方法获取
     * @param bucketName  bucketName
     * @param objectName  文件名称,如:2021/11/28/test.zip
     * @param partNumbers 分片partNumber集合
     * @param time        过期时间,默认10分钟
     * @param timeUnit    过期时间单位,默认分钟
     * @return
     */
    public MultiPartUploadInfo getPresignedMultipartUploadUrlsByPartNumbers(String uploadId, String bucketName, String path, String objectName, List<Integer> partNumbers, Integer time, TimeUnit timeUnit) throws MinioException {
        List<String> partUrlList = new ArrayList<>();
        try {
            objectName = (StringUtils.hasText(path) ? MinioUtil.getPath(path) : "") + MinioUtil.getObjectName(objectName);
            Map<String, String> paramsMap = new HashMap<>(2);
            paramsMap.put("uploadId", uploadId);
            for (Integer partNumber : partNumbers) {
                paramsMap.put("partNumber", String.valueOf(partNumber));
                // 获取上传 url
                String uploadUrl = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                        // 注意此处指定请求方法为 PUT,前端需对应,否则会报 `SignatureDoesNotMatch` 错误
                        .method(Method.PUT)
                        .bucket(bucketName)
                        .object(objectName)
                        // 指定上传连接有效期
                        .expiry(time, timeUnit)
                        .extraQueryParams(paramsMap).build());
                partUrlList.add(uploadUrl);
            }
        } catch (IOException | InsufficientDataException | InternalException | InvalidKeyException |
                 NoSuchAlgorithmException | XmlParserException e) {
            throw new MinioException(e.getMessage());
        }

        return MultiPartUploadInfo.builder()
                .uploadId(uploadId)
                .fileName(objectName)
                .expiryTime(MinioUtil.getLocalDateTime(time, timeUnit))
                .uploadUrls(partUrlList)
                .build();
    }

    /**
     * 初始化分片上传
     *
     * @param objectName 文件名称
     * @return
     * @throws MinioException
     */
    public InitiateMultipartUploadResult initMultiPartUpload(String objectName) throws MinioException {
        return initMultiPartUpload(getBucketName(), objectName);
    }

    /**
     * 初始化分片上传
     *
     * @param bucketName bucketName
     * @param objectName 文件名称
     * @return
     * @throws MinioException
     */
    public InitiateMultipartUploadResult initMultiPartUpload(String bucketName, String objectName) throws MinioException {
        return initMultiPartUpload(bucketName, null, objectName);
    }

    /**
     * 初始化分片上传
     *
     * @param bucketName bucketName
     * @param objectName 文件名称
     * @return
     * @throws MinioException
     */
    public InitiateMultipartUploadResult initMultiPartUpload(String bucketName, String path, String objectName) throws MinioException {
        return initMultiPartUpload(bucketName, path, objectName, "application/octet-stream");
    }

    /**
     * 初始化分片上传
     *
     * @param bucketName  bucketName
     * @param objectName  文件名称
     * @param contentType contentType
     * @return
     * @throws MinioException
     */
    public InitiateMultipartUploadResult initMultiPartUpload(String bucketName, String path, String objectName, String contentType) throws MinioException {
        try {
            objectName = (StringUtils.hasText(path) ? MinioUtil.getPath(path) : "") + MinioUtil.getObjectName(objectName);
            return minioAsyncClient.initMultiPartUpload(bucketName, null, objectName, MinioUtil.getHeader(contentType), null);
        } catch (IOException | InsufficientDataException | InternalException | InvalidKeyException |
                 NoSuchAlgorithmException | XmlParserException | ExecutionException | InterruptedException e) {
            throw new MinioException(e.getMessage());
        }
    }

    /**
     * 合并分片
     *
     * @param objectName
     * @param uploadId
     * @return
     * @throws MinioException
     */
    public String mergeMultiPartUpload(String objectName, String uploadId) throws MinioException {
        return mergeMultiPartUpload(getBucketName(), objectName, uploadId);
    }

    /**
     * 合并分片
     *
     * @param bucketName
     * @param objectName
     * @param uploadId
     * @return
     * @throws MinioException
     */
    public String mergeMultiPartUpload(String bucketName, String objectName, String uploadId) throws MinioException {
        return mergeMultiPartUpload(bucketName, objectName, uploadId, 1000);
    }


    /**
     * 合并分片
     *
     * @param bucketName
     * @param objectName
     * @param uploadId
     * @return
     * @throws MinioException
     */
    public String mergeMultiPartUpload(String bucketName, String objectName, String uploadId, Integer maxParts) throws MinioException {
        try {
            ListPartsResponse partsResponse = minioAsyncClient.listMultipart(bucketName, null, MinioUtil.getObjectName(objectName), maxParts, 0, uploadId, null, null);
            if (null == partsResponse) {
                throw new MinioException("分片列表为空");
            }
            List<Part> partList = partsResponse.result().partList();
            Part[] parts = new Part[partList.size()];
            partList.toArray(parts);
            ObjectWriteResponse writeResponse = minioAsyncClient.mergeMultipartUpload(bucketName, null, MinioUtil.getObjectName(objectName), uploadId, parts, null, null);
            if (null == writeResponse) {
                throw new MinioException("分片合并失败");
            }
            return getAddress(writeResponse.region());
        } catch (ErrorResponseException | IOException | InsufficientDataException | InternalException |
                 InvalidKeyException | InvalidResponseException | NoSuchAlgorithmException | XmlParserException |
                 ServerException | ExecutionException | InterruptedException e) {
            throw new MinioException(e.getMessage());
        }
    }

    /**
     * 获取已上传的分片列表
     *
     * @param objectName
     * @param uploadId
     * @return
     * @throws MinioException
     */
    public List<Integer> listUploadMultiPart(String objectName, String uploadId) throws MinioException {
        return listUploadMultiPart(getBucketName(), objectName, uploadId);
    }

    /**
     * 获取已上传的分片列表
     *
     * @param bucketName
     * @param objectName
     * @param uploadId
     * @return
     * @throws MinioException
     */
    public List<Integer> listUploadMultiPart(String bucketName, String objectName, String uploadId) throws MinioException {
        return listUploadMultiPart(bucketName, objectName, uploadId, 1000);
    }

    /**
     * 获取已上传的分片列表
     *
     * @param bucketName
     * @param objectName
     * @param uploadId
     * @param maxParts
     * @return
     * @throws MinioException
     */
    public List<Integer> listUploadMultiPart(String bucketName, String objectName, String uploadId, Integer maxParts) throws MinioException {
        ListPartsResponse partsResponse;
        try {
            partsResponse = minioAsyncClient.listMultipart(bucketName, null, MinioUtil.getObjectName(objectName), maxParts, 0, uploadId, null, null);
        } catch (NoSuchAlgorithmException | IOException | InvalidKeyException | ExecutionException |
                 InterruptedException e) {
            throw new MinioException(e.getMessage());
        }
        if (null == partsResponse) {
            return Collections.emptyList();
        }
        return partsResponse.result().partList().stream().map(Part::partNumber).collect(Collectors.toList());
    }

    /**
     * 获得 当前日期分割目录,如:2021/11/28
     *
     * @return
     */
    public String getDatePath() {
        return String.join(MinioConstant.URI_DELIMITER, MinioUtil.getDateFolder());
    }

    /**
     * 获得文件外链,永久外链,需要服务端设置指定bucket为全部可访问
     *
     * @param bucket    bucket名称
     * @param finalPath 路径及文件名,如 2021/11/20/test.zip
     * @return
     */
    public String gatewayUrl(String bucket, String finalPath) {
        finalPath = finalPath.startsWith(MinioConstant.URI_DELIMITER) ? finalPath.substring(finalPath.indexOf(MinioConstant.URI_DELIMITER) + 1) : finalPath;
        return getAddress(minioConfig.getEndpoint() + MinioConstant.URI_DELIMITER + bucket + MinioConstant.URI_DELIMITER + finalPath);
    }

    /**
     * 获得文件访问地址
     *
     * @return
     */
    public String getAddress(String url) {
        String address = "".equals(minioConfig.getAddress().trim()) ? minioConfig.getEndpoint() : minioConfig.getAddress();
        return url.replace(minioConfig.getEndpoint(), address);
    }

    /**
     * 默认BucketName
     *
     * @return
     */
    public String getBucketName() {
        if (!StringUtils.hasText(minioConfig.getBucketName())) {
            throw new RuntimeException("未配置默认 BucketName");
        }
        return minioConfig.getBucketName();
    }

}

Controller类

package com.ygsoft.jt.teng.cp.minio.controller;

import com.ygsoft.jt.teng.cp.minio.config.MinioConfig;
import com.ygsoft.jt.teng.cp.minio.constant.MinioConstant;
import com.ygsoft.jt.teng.cp.minio.enums.PolicyType;
import com.ygsoft.jt.teng.cp.minio.service.MinioService;
import io.minio.errors.MinioException;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
 * @author hhong2 <br>
 * @version 1.0.0 2023/11/3 10:12 <br>
 * @since JDK 1.8.0
 */
@RestController
public class testController {
    @Resource
    private MinioService minioService;
    @Resource
    private MinioConfig minioConfig;
    @PostMapping("/minio/upload")
    public String upload(MultipartFile file, String folderName) throws IOException, MinioException, NoSuchAlgorithmException, InvalidKeyException {
        // 如果bucket不存在则创建一个当前配置的可读可写权限的bucket
        if (!minioService.bucketExists(minioConfig.getBucketName())){
            minioService.createBucket(minioConfig.getBucketName(), PolicyType.READ_WRITE);
        }
        // 创建目录
        minioService.createFolder(minioConfig.getBucketName(),folderName);
        // 上传图片
        minioService.putObject(minioConfig.getBucketName(),folderName+MinioConstant.URI_DELIMITER+file.getOriginalFilename(),file.getContentType(),file.getInputStream());
        // 返回图片下载地址
        return minioService.getObjectUrl(minioConfig.getBucketName(),folderName+MinioConstant.URI_DELIMITER+file.getOriginalFilename(),false,-1);
    }
}

这样不仅在typora里面可以实现私有化图床的效果,在中小型企业里面也可以完全自己搭一个图床来统一管理和备份了;封装了一个minioService的组件和完整流程的有需要的同学留言,我发压缩包;Typora自动上传图片,springboot集成Minio做私有化图床

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值