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做私有化图床