MinIO中文文档:/
MinIO搭建文件服务器:
JAVA Client快速入门:
MinIO 是一个基于Apache License v2.0开源协议的对象存储服务。它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等。
MinIO是一个非常轻量的服务,可以很简单的和其他应用的结合,类似 NodeJS, Redis 或者 MySQL。
安装(略)
使用以下命令在 Windows 主机上运行独立的 MinIO 服务器。 将“D:”替换为您希望 MinIO 存储数据的驱动器或目录的路径。将终端或 powershell 目录更改为 可执行文件的位置
server D:
结果展示,分析
访问
浏览器输入:localhost:9000/minio/
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency><dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>7.1.0</version>
</dependency>
server:port: 8889
# spring
spring:# 数据库datasource:driver-class-name: sql.jdbc.Driverurl: username: password: type: com.alibaba.druid.pool.DruidDataSource
# data:
# solr:
# host: localhost:8081/solr
# elasticsearch:
# rest:
# uris: localhost:9200mybatis-plus:mapper-locations: classpath:mapper/*.xmlconfiguration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl# 配置minio
minio:endpoint: localhost:9000 # 节点地址# 账号accessKey: minioadmin# 密码secretKey: minioadminassets-bucket: assets # 存储桶名称 bucketName
#
solr-core:default: library_core
读取配置的minioProperties,并配置MinioClient Bean
MinioConfiguration – MinioClient
@Configuration
@ConditionalOnBean(MinioProperties.class)
public class MinioConfiguration {//minio配置类,@Autowiredprivate MinioProperties minioProperties;//初始化minio客户端对象MinioClient@Beanpublic MinioClient minioClient() {return MinioClient.builder().Endpoint()).AccessKey(), SecretKey()).build();}
}
MinioProperties
@Data
@Component
@ConfigurationProperties(prefix = "minio")
public class MinioProperties {private String endpoint;private String accessKey;private String secretKey;private String bucketName;private String accessUrl;
}
@Slf4j
@Data
@Component
public class MinioUtil {@Autowiredprivate MinioClient client;@Value("${minio.assets-bucket}")private String bucket;/*** 创建文件夹*/public Boolean mkdir(String objName) throws Exception {client.putObject(PutObjectArgs.builder().bucket(bucket).object(objName).stream(new ByteArrayInputStream(new byte[]{}), 0, 0).build());return true;}/**上传文件*/public Boolean uploadFile(String objName, InputStream stream, Long fileSize, String contentType) throws Exception {client.putObject(PutObjectArgs.builder().bucket(bucket).object(objName).stream(stream, fileSize, 0).contentType(contentType).build());return true;}/*** 删除文件*/public Boolean delFile(String objName) throws Exception {veObject(RemoveObjectArgs.builder().bucket(bucket).object(objName).build());return true;}/*** 获取文件下载的url*/public String getFileUrl(String objName) throws Exception {return client.presignedGetObject(bucket, objName);}@PostConstructpublic void init() throws Exception {if (!client.bucketExists(BucketExistsArgs.builder().bucket(bucket).build())) {client.makeBucket(MakeBucketArgs.builder().bucket(bucket).build());log.info("create default bucket successfully");} else {log.info("default bucket already exists");}}
}
@Component
public class MinioUtil {@Autowiredprivate MinioClient minioClient;private static final int DEFAULT_EXPIRY_TIME = 7 * 24 * 3600;/*** 检查存储桶是否存在*/public boolean bucketExists(String bucketName) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException {boolean flag = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());if (flag) {return true;}return false;}/*创建存储桶 */public boolean makeBucket(String bucketName) throws IOException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, ServerException, ErrorResponseException, XmlParserException, InvalidBucketNameException, InsufficientDataException, InternalException, RegionConflictException {boolean flag = bucketExists(bucketName);if (!flag) {minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());return true;} else {return false;}}/*** 列出所有存储桶名称*/public List<String> listBucketNames() throws IOException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, ServerException, ErrorResponseException, XmlParserException, InvalidBucketNameException, InsufficientDataException, InternalException {List<Bucket> bucketList = listBuckets();List<String> bucketListName = new ArrayList<>();for (Bucket bucket : bucketList) {bucketListName.add(bucket.name());}return bucketListName;}/*** 列出所有存储桶*/public List<Bucket> listBuckets() throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException {return minioClient.listBuckets();}/*** 删除存储桶*/public boolean removeBucket(String bucketName) throws IOException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, ServerException, ErrorResponseException, XmlParserException, InvalidBucketNameException, InsufficientDataException, InternalException {boolean flag = bucketExists(bucketName);if (flag) {Iterable<Result<Item>> myObjects = listObjects(bucketName);for (Result<Item> result : myObjects) {Item item = ();// 有对象文件,则删除失败if (item.size() > 0) {return false;}}// 删除存储桶,注意,只有存储桶为空时才能删除成功。veBucket(RemoveBucketArgs.builder().bucket(bucketName).build());flag = bucketExists(bucketName);if (!flag) {return true;}}return false;}/*** 列出存储桶中的所有对象名称*/public List<String> listObjectNames(String bucketName) throws IOException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, ServerException, ErrorResponseException, XmlParserException, InvalidBucketNameException, InsufficientDataException, InternalException {List<String> listObjectNames = new ArrayList<>();boolean flag = bucketExists(bucketName);if (flag) {Iterable<Result<Item>> myObjects = listObjects(bucketName);for (Result<Item> result : myObjects) {Item item = ();listObjectNames.add(item.objectName());}}return listObjectNames;}/*** 列出存储桶中的所有对象*/public Iterable<Result<Item>> listObjects(String bucketName) throws IOException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, ServerException, ErrorResponseException, XmlParserException, InvalidBucketNameException, InsufficientDataException, InternalException {boolean flag = bucketExists(bucketName);if (flag) {return minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).build());}return null;}/*** 通过InputStream上传对象*/public boolean putObject(String bucketName, String objectName, InputStream stream, String contentType) throws IOException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, ServerException, ErrorResponseException, XmlParserException, InvalidBucketNameException, InsufficientDataException, InternalException {boolean flag = bucketExists(bucketName);if (flag) {minioClient.putObject( PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(stream, stream.available(), -1).contentType(contentType).build());ObjectStat statObject = statObject(bucketName, objectName);if (statObject != null && statObject.length() > 0) {return true;}}return false;}/*** 以流的形式获取一个文件对象*/public InputStream getObject(String bucketName, String objectName) throws IOException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, ServerException, ErrorResponseException, XmlParserException, InvalidBucketNameException, InsufficientDataException, InternalException {boolean flag = bucketExists(bucketName);if (flag) {ObjectStat statObject = statObject(bucketName, objectName);if (statObject != null && statObject.length() > 0) {InputStream stream = Object(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());return stream;}}return null;}/*** 以流的形式获取一个文件对象(断点下载)*/public InputStream getObject(String bucketName, String objectName, long offset, Long length) throws IOException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, ServerException, ErrorResponseException, XmlParserException, InvalidBucketNameException, InsufficientDataException, InternalException {boolean flag = bucketExists(bucketName);if (flag) {ObjectStat statObject = statObject(bucketName, objectName);if (statObject != null && statObject.length() > 0) {InputStream stream = Object(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());return stream;}}return null;}/*** 下载并将文件保存到本地*/public boolean getObject(String bucketName, String objectName, String fileName) throws IOException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, ServerException, ErrorResponseException, XmlParserException, InvalidBucketNameException, InsufficientDataException, InternalException {boolean flag = bucketExists(bucketName);if (flag) {ObjectStat statObject = statObject(bucketName, objectName);if (statObject != null && statObject.length() > 0) {Object(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());return true;}}return false;}/*** 删除一个对象*/public boolean removeObject(String bucketName, String objectName) throws IOException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, ServerException, ErrorResponseException, XmlParserException, InvalidBucketNameException, InsufficientDataException, InternalException {boolean flag = bucketExists(bucketName);if (flag) {veObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build());return true;}return false;}/*** 删除指定桶的多个文件对象,返回删除错误的对象列表,全部删除成功,返回空列表*/public List<String> removeObject(String bucketName, List<DeleteObject> objects) throws IOException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, ServerException, ErrorResponseException, XmlParserException, InvalidBucketNameException, InsufficientDataException, InternalException {List<String> deleteErrorNames = new ArrayList<>();boolean flag = bucketExists(bucketName);if (flag) {Iterable<Result<DeleteError>> results = veObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(objects).build());for (Result<DeleteError> result : results) {DeleteError error = ();deleteErrorNames.add(error.objectName());}}return deleteErrorNames;}/*** 生成一个给HTTP GET请求用的presigned URL。* 浏览器/移动端的客户端可以用这个URL进行下载,即使其所在的存储桶是私有的。这个presigned URL可以设置一个失效时间,默认值是7天。** @param bucketName 存储桶名称* @param objectName 存储桶里的对象名称* @param expires 失效时间(以秒为单位),默认是7天,不得大于七天 */public String getPresignedObjectUrl(String bucketName, String objectName, Integer expires) throws IOException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, ServerException, ErrorResponseException, XmlParserException, InvalidBucketNameException, InsufficientDataException, InternalException, InvalidExpiresRangeException {boolean flag = bucketExists(bucketName);String url = "";if (flag) {if (expires < 1 || expires > DEFAULT_EXPIRY_TIME) {throw new InvalidExpiresRangeException(expires,"expires must be in range of 1 to " + DEFAULT_EXPIRY_TIME);}url = PresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(bucketName).object(objectName).expiry(expires).build());}return url;}/*** 生成一个给HTTP PUT请求用的presigned URL。* 浏览器/移动端的客户端可以用这个URL进行上传,即使其所在的存储桶是私有的。这个presigned URL可以设置一个失效时间,默认值是7天。*/public String getPresignedObjectGetPutUrl(String bucketName, String objectName, Integer expires) throws IOException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, ServerException, ErrorResponseException, XmlParserException, InvalidBucketNameException, InsufficientDataException, InternalException, InvalidExpiresRangeException {boolean flag = bucketExists(bucketName);String url = "";if (flag) {if (expires < 1 || expires > DEFAULT_EXPIRY_TIME) {throw new InvalidExpiresRangeException(expires,"expires must be in range of 1 to " + DEFAULT_EXPIRY_TIME);}Map<String, String> reqParams = new HashMap<String, String>();reqParams.put("response-content-type", "application/json");url = PresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.PUT).bucket(bucketName).object(objectName).expiry(expires).extraQueryParams(reqParams).build());}return url;}/*** 获取对象的元数据*/public ObjectStat statObject(String bucketName, String objectName) throws IOException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, ServerException, ErrorResponseException, XmlParserException, InvalidBucketNameException, InsufficientDataException, InternalException {boolean flag = bucketExists(bucketName);if (flag) {ObjectStat statObject = minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());return statObject;}return null;}/*** 文件访问路径*/public String getObjectUrl(String bucketName, String objectName) throws IOException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, ServerException, ErrorResponseException, XmlParserException, InvalidBucketNameException, InsufficientDataException, InternalException {boolean flag = bucketExists(bucketName);String url = "";if (flag) {url = ObjectUrl(bucketName, objectName);}return url;}/*** 设定存储桶策略 */public void setBucketPolicy(String bucketName, String policyJson) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException {minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucketName).config(policyJson).build());}
}
@Slf4j
@RestController
public class OssController {@Autowiredprivate MinioUtil minioUtil;@Autowiredprivate MinioProperties minioProperties;/*** 文件上传接口* @param file 上传的文件对象* @return 上传成功返回文件url 图片 txt 文件支持通过url 浏览器直接预览*/@PostMapping("/upload")public BaseRespEntity MinIOUpload(MultipartFile file) {if (file.isEmpty() || Size() == 0) {("文件为空");}try {//如果默认的桶不存在,则创建if (!minioUtil.BucketName())) {BucketName());}String fileName = OriginalFilename();String newName = "project-file/" + UUID.randomUUID().toString().replaceAll("-", "")+ fileName.substring(fileName.lastIndexOf("."));InputStream inputStream = InputStream();// 使用putObject上传一个文件到存储桶中。minioUtil.BucketName(), newName, inputStream, ContentType());inputStream.close();String url = BucketName(), newName);return BaseRespEntity.AccessUrl(url));} catch (Exception e) {e.printStackTrace();("上传失败");}}private String getAccessUrl(String url) {AccessUrl() + StrUtil.subAfter(url, BucketName(), false);}/*** 文件下载** @param filename 文件名* @param httpResponse 接口返回对象*/@GetMapping("download/{filename}")public void downloadFiles(@PathVariable("filename") String filename, HttpServletResponse httpResponse) {try {InputStream object = BucketName(), "/project-file/" + filename);byte buf[] = new byte[1024];int length = set();httpResponse.setHeader("Content-Disposition", "attachment;filename=" + de(filename, "UTF-8"));httpResponse.setContentType("application/octet-stream");httpResponse.setCharacterEncoding("utf-8");OutputStream outputStream = OutputStream();while ((length = ad(buf)) > 0) {outputStream.write(buf, 0, length);}outputStream.close();} catch (Exception ex) {("文件下载失败:{}", ex.getMessage());}}/*** 创建储存桶** @param bucketName*/private void createBucket(String bucketName) {/*policy 的设定可以参照aws 中文档说明*//*.html*/StringBuilder policyJsonBuilder = new StringBuilder();policyJsonBuilder.append("{n");policyJsonBuilder.append(" "Statement": [n");policyJsonBuilder.append(" {n");policyJsonBuilder.append(" "Action": [n");policyJsonBuilder.append(" "s3:GetBucketLocation",n");policyJsonBuilder.append(" "s3:ListBucket"n");policyJsonBuilder.append(" ],n");policyJsonBuilder.append(" "Effect": "Allow",n");policyJsonBuilder.append(" "Principal": "*",n");policyJsonBuilder.append(" "Resource": "arn:aws:s3:::" + bucketName + ""n");policyJsonBuilder.append(" },n");policyJsonBuilder.append(" {n");policyJsonBuilder.append(" "Action": "s3:GetObject",n");policyJsonBuilder.append(" "Effect": "Allow",n");policyJsonBuilder.append(" "Principal": "*",n");policyJsonBuilder.append(" "Resource": "arn:aws:s3:::" + bucketName + "/project-file*"n");policyJsonBuilder.append(" }n");policyJsonBuilder.append(" ],n");policyJsonBuilder.append(" "Version": "2012-10-17"n");policyJsonBuilder.append("}n");try {minioUtil.makeBucket(bucketName);//创建桶minioUtil.setBucketPolicy(bucketName, String());} catch (Exception e) {("创建存储桶失败:{}", e);}}
}
本文发布于:2024-02-05 08:02:15,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170727886064763.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |