分布式对象存储服务minio安装和部署
一、服务器安装minio
1.进行下载
下载地址:
https://dl.min.io/server/minio/release/linux-amd64/minio
2.新建minio安装目录,执行如下命令
mkdir -p /home/minio/data
把二进制文件上传到安装目录后,执行:
chmod +x minio //给予权限//注意:以前的老版本minio的配置中,配置用户名和密码时,是这两个参数:
MINIO_ACCESS_KEY 和MINIO_SECRET_KEY
而现在比较新的版本的minio,需要替换成MINIO_ROOT_USER和MINIO_ROOT_PASSWORD
export MINIO_ROOT_USER=fsp-manage
export MINIO_ROOT_PASSWORD=springboot-fsp-manage
./minio server /home/minio/data //启动
后台启动,并打印日志
自定义端口方式:自定义启动端口号以及控制台端口号,不设置则控制台会自动配置其他端口号,非常不方便
nohup ./minio server --address :9000 --console-address :9001 /home/minio/data > /home/minio/data/minio.log &
ps -ef|grep minio
二、进行访问,并设置桶
地址:http://127.0.0.1:9000
三、springboot进行实现
1.引入依赖
!-- minio 相关依赖 --> io.minio minio 3.0.10 com.alibaba fastjson 1.2.51 org.springframework.boot spring-boot-starter-thymeleaf
2.在 application.yml 文件中加入 MinIO 服务器的相关信息
minio: endpoint: http://serverip port: 9002 accessKey: fsp-manage secretKey: springboot-fsp-manage bucketName: fsp-dev secure: false
3.创建实体类
这一步,我们将配置文件中 minio 的配置信息通过注解的方式注入到 MinioProp 这个实体中,方便后面我们使用
package com.xiaomifeng1010.minio.configuration; import io.minio.MinioClient;import io.minio.errors.InvalidPortException;import lombok.Getter;import lombok.Setter;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.stereotype.Component; @Configuration@Component@ConfigurationProperties(prefix = "minio")@Getter@Setterpublic class MinioConfig { private String endpoint; private int port; private String accessKey; private String secretKey; private Boolean secure; private String bucketName; @Bean public MinioClient getMinioClient() throws InvalidPortException { MinioClient minioClient = MinioClient.builder().endpoint(endpoint, port, secure) .credentials(accessKey, secretKey) .build(); return minioClient; }//// @Bean(name = "multipartResolver")// public MultipartResolver multipartResolver(){// CommonsMultipartResolver resolver = new CommonsMultipartResolver();// resolver.setDefaultEncoding("UTF-8");// //resolveLazily属性启用是为了推迟文件解析,以在在UploadAction中捕获文件大小异常// resolver.setResolveLazily(true);// resolver.setMaxInMemorySize(40960);// //上传文件大小 50M 50*1024*1024// resolver.setMaxUploadSize(50*1024*1024);// return resolver;// }}
如何你要配置ip和port在同一个参数中,不分开,或者是直接配置域名(域名映射了ip和port),那么配置的yml 修改如下:
把port注释掉,同时配置类也修改一下就可以了:
5、上传工具类
package com.xiaomifeng.minio.util; import io.minio.*;import io.minio.errors.*;import io.minio.http.Method;import io.minio.messages.Bucket;import io.minio.messages.DeleteError;import io.minio.messages.DeleteObject;import io.minio.messages.Item;import lombok.extern.slf4j.Slf4j;import org.apache.commons.lang.StringUtils;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import org.springframework.web.multipart.MultipartFile; import javax.servlet.ServletOutputStream;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.InputStream;import java.nio.charset.StandardCharsets;import java.security.InvalidKeyException;import java.security.NoSuchAlgorithmException;import java.util.ArrayList;import java.util.List; @Component@Slf4jpublic class MinioClientUtils { @Autowired private 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 = false; flag = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build()); if (flag) { return true; } return false; } public boolean makeBucket(String bucketName) throws IOException, InvalidKeyException, InvalidResponseException, RegionConflictException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException { boolean flag = bucketExists(bucketName); if (!flag) { minioClient.makeBucket( MakeBucketArgs.builder().bucket(bucketName).build()); return true; } else { return false; } } public List listBucketNames() throws IOException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, ServerException, ErrorResponseException, XmlParserException, InvalidBucketNameException, InsufficientDataException, InternalException { List bucketList = listBuckets(); List bucketListName = new ArrayList<>(); for (Bucket bucket : bucketList) { bucketListName.add(bucket.name()); } return bucketListName; } public List listBuckets() throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException { return minioClient.listBuckets(); } public boolean removeBucket(String bucketName) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException { boolean flag = bucketExists(bucketName); if (flag) { Iterable> myObjects = listObjects(bucketName); for (Result- result : myObjects) { Item item = result.get(); // 有对象文件,则删除失败 if (item.size() > 0) { return false; } } // 删除存储桶,注意,只有存储桶为空时才能删除成功。 minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build()); flag = bucketExists(bucketName); if (!flag) { return true; } } return false; } public List
listObjectNames(String bucketName) throws XmlParserException, IOException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, ServerException, ErrorResponseException, InvalidBucketNameException, InsufficientDataException, InternalException { List listObjectNames = new ArrayList<>(); boolean flag = bucketExists(bucketName); if (flag) { Iterable> myObjects = listObjects(bucketName); for (Result- result : myObjects) { Item item = result.get(); listObjectNames.add(item.objectName()); } } return listObjectNames; } public Iterable
> listObjects(String bucketName) throws XmlParserException, IOException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, ServerException, ErrorResponseException, InvalidBucketNameException, InsufficientDataException, InternalException { boolean flag = bucketExists(bucketName); if (flag) { return minioClient.listObjects( ListObjectsArgs.builder().bucket(bucketName).build()); } return null; } public boolean uploadObject(String bucketName, String objectName, String fileName) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException { boolean flag = bucketExists(bucketName); if (flag) { minioClient.uploadObject( UploadObjectArgs.builder().bucket(bucketName).object(objectName).filename(fileName).build()); ObjectStat statObject = statObject(bucketName, objectName); if (statObject != null && statObject.length() > 0) { return true; } } return false; } public void putObject(String bucketName, MultipartFile multipartFile, String filename) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException { PutObjectOptions putObjectOptions = new PutObjectOptions(multipartFile.getSize(), PutObjectOptions.MIN_MULTIPART_SIZE); putObjectOptions.setContentType(multipartFile.getContentType()); minioClient.putObject( PutObjectArgs.builder().bucket(bucketName).object(filename).stream( multipartFile.getInputStream(), multipartFile.getSize(), -1).contentType(multipartFile.getContentType()) .build()); } public boolean putObject(String bucketName, String objectName, InputStream inputStream,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( //不清楚文件的大小时,可以传-1,10485760。如果知道大小也可以传入size,partsize。 inputStream, -1, 10485760) .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, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException { boolean flag = bucketExists(bucketName); if (flag) { ObjectStat statObject = statObject(bucketName, objectName); if (statObject != null && statObject.length() > 0) { InputStream stream = minioClient.getObject( GetObjectArgs.builder() .bucket(bucketName) .object(objectName) .build()); return stream; } } return null; } public InputStream getObject(String bucketName, String objectName, long offset, Long length) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException { boolean flag = bucketExists(bucketName); if (flag) { ObjectStat statObject = statObject(bucketName, objectName); if (statObject != null && statObject.length() > 0) { InputStream stream = minioClient.getObject( GetObjectArgs.builder() .bucket(bucketName) .object(objectName) .offset(1024L) .length(4096L) .build()); return stream; } } return null; } public boolean downloadObject(String bucketName, String objectName, String fileName) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException { boolean flag = bucketExists(bucketName); if (flag) { ObjectStat statObject = statObject(bucketName, objectName); if (statObject != null && statObject.length() > 0) { minioClient.downloadObject(DownloadObjectArgs.builder() .bucket(bucketName) .object(objectName) .filename(fileName) .build()); return true; } } return false; } public boolean removeObject(String bucketName, String objectName) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException { boolean flag = bucketExists(bucketName); if (flag) { minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build()); return true; } return false; } public List removeObjects(String bucketName, List objectNames) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException { List deleteErrorNames = new ArrayList<>(); boolean flag = bucketExists(bucketName); if (flag) { Iterable> results = minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(objectNames).build()); for (Result result : results) { DeleteError error = result.get(); deleteErrorNames.add(error.objectName()); } } return deleteErrorNames; } public String getPresignedObjectUrl(String bucketName, String objectName, Integer expires) throws InvalidExpiresRangeException, IOException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, ServerException, ErrorResponseException, XmlParserException, InvalidBucketNameException, InsufficientDataException, InternalException { 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); } try { url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder() .method(Method.GET) .bucket(bucketName) .object(objectName) .expiry(expires)//动态参数 // .expiry(24 * 60 * 60)//用秒来计算一天时间有效期// .expiry(1, TimeUnit.DAYS)//按天传参// .expiry(1, TimeUnit.HOURS)//按小时传参数 .build()); } catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidBucketNameException | InvalidExpiresRangeException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) { e.printStackTrace(); } } return url; } public String presignedPutObject(String bucketName, String objectName, Integer expires) throws IOException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, ServerException, ErrorResponseException, XmlParserException, InvalidBucketNameException, InsufficientDataException, InternalException { boolean flag = bucketExists(bucketName); String url = ""; if (flag) { if (expires < 1 || expires > DEFAULT_EXPIRY_TIME) { try { throw new InvalidExpiresRangeException(expires,"expires must be in range of 1 to " + DEFAULT_EXPIRY_TIME); } catch (InvalidExpiresRangeException e) { e.printStackTrace(); } } try { url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder() .method(Method.PUT) .bucket(bucketName) .object(objectName) .expiry(expires)//动态参数 // .expiry(24 * 60 * 60)//用秒来计算一天时间有效期// .expiry(1, TimeUnit.DAYS)//按天传参// .expiry(1, TimeUnit.HOURS)//按小时传参数 .build()); } catch (ErrorResponseException | InsufficientDataException e) { e.printStackTrace(); } catch (InternalException e) { log.error("InternalException",e); } catch (InvalidBucketNameException e) { log.error("InvalidBucketNameException",e); } catch (InvalidExpiresRangeException e) { log.error("InvalidExpiresRangeException",e); } catch (InvalidKeyException e) { log.error("InvalidKeyException",e); } catch (InvalidResponseException e) { log.error("InvalidResponseException",e); } catch (IOException e) { log.error("IOException",e); } catch (NoSuchAlgorithmException e) { log.error("NoSuchAlgorithmException",e); } catch (ServerException e) { log.error("ServerException",e); } catch (XmlParserException e) { log.error("XmlParserException",e); } } 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 = null; try { statObject = minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build()); } catch (ErrorResponseException e) { log.error("ErrorResponseException",e); } catch (InsufficientDataException e) { log.error("ErrorResponseException",e); e.printStackTrace(); } catch (InternalException e) { log.error("InternalException",e); } catch (InvalidBucketNameException e) { log.error("InvalidBucketNameException",e); } catch (InvalidKeyException e) { log.error("InvalidKeyException",e); } catch (InvalidResponseException e) { log.error("InvalidResponseException",e); } catch (IOException e) { log.error("IOException",e); } catch (NoSuchAlgorithmException e) { log.error("NoSuchAlgorithmException",e); } catch (ServerException e) { log.error("ServerException",e); } catch (XmlParserException e) { log.error("XmlParserException",e); } 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) { try { url = minioClient.getObjectUrl(bucketName, objectName); } catch (ErrorResponseException e) { log.error("XmlParserException",e); } catch (InsufficientDataException e) { log.error("InsufficientDataException",e); } catch (InternalException e) { log.error("InternalException",e); } catch (InvalidBucketNameException e) { log.error("InvalidBucketNameException",e); } catch (InvalidKeyException e) { log.error("InvalidKeyException",e); } catch (InvalidResponseException e) { log.error("InvalidResponseException",e); } catch (IOException e) { log.error("IOException",e); } catch (NoSuchAlgorithmException e) { log.error("NoSuchAlgorithmException",e); } catch (ServerException e) { log.error("ServerException",e); } catch (XmlParserException e) { log.error("XmlParserException",e); } } return url; } public void downloadFile(String bucketName, String fileName, String originalName, HttpServletResponse response) { try { InputStream file = minioClient.getObject(GetObjectArgs.builder() .bucket(bucketName) .object(fileName) .build()); String filename = new String(fileName.getBytes("ISO8859-1"), StandardCharsets.UTF_8); if (StringUtils.isNotEmpty(originalName)) { fileName = originalName; } response.setHeader("Content-Disposition", "attachment;filename=" + filename); ServletOutputStream servletOutputStream = response.getOutputStream(); int len; byte[] buffer = new byte[1024]; while ((len = file.read(buffer)) > 0) { servletOutputStream.write(buffer, 0, len); } servletOutputStream.flush(); file.close(); servletOutputStream.close(); } catch (ErrorResponseException e) { log.error("ErrorResponseException",e); } catch (Exception e) { log.error("Exception",e); } }}
6.controller接口
package com.dcboot.module.minio.controller; import cn.hutool.core.io.FileUtil;import com.dcboot.base.util.ApiResult;import com.dcboot.module.minio.configuration.MinioConfig;import com.dcboot.module.minio.dto.response.MinioResponseDTO;import com.dcboot.module.minio.entity.MinioFile;import com.dcboot.module.util.MinioClientUtils;import io.swagger.annotations.Api;import io.swagger.annotations.ApiImplicitParam;import io.swagger.annotations.ApiOperation;import lombok.AllArgsConstructor;import lombok.extern.slf4j.Slf4j;import org.apache.commons.collections4.CollectionUtils;import org.apache.commons.lang3.RandomStringUtils;import org.apache.commons.lang3.math.NumberUtils;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.*;import org.springframework.web.multipart.MultipartFile; import java.io.FileInputStream;import java.time.Instant;import java.util.ArrayList;import java.util.List; @Controller@RequestMapping("/fileHandle")@Slf4j@AllArgsConstructor@Api(tags = "文件处理模块")public class FileHandleController { private MinioClientUtils minioClientUtils; private MinioConfig minioConfig; @PostMapping(value = {"/admin/uploadFile","/web/uploadFile"}) @ResponseBody @ApiOperation(value = "上传文件,支持批量上传") @ApiImplicitParam(name = "files",value = "文件对象",dataType = "File") public ApiResult uploadFile(@RequestParam("files") List files) { log.info(files.toString()); if (CollectionUtils.isEmpty(files)){ return ApiResult.error("未选择文件!"); } List MinioResponseDTOList=new ArrayList<>(); for (MultipartFile file : files) { String originalFilename = file.getOriginalFilename();// 获取文件拓展名 String extName = FileUtil.extName(originalFilename); log.info("文件拓展名:"+extName);// 生成新的文件名,存入到minio long millSeconds = Instant.now().toEpochMilli(); String minioFileName=millSeconds+ RandomStringUtils.randomNumeric(12)+"."+extName; String contentType = file.getContentType(); log.info("文件mime:{}",contentType);// 返回文件大小,单位字节 long size = file.getSize(); log.info("文件大小:"+size); try { String bucketName = minioConfig.getBucketName(); minioClientUtils.putObject(bucketName,file,minioFileName); String fileUrl = minioClientUtils.getObjectUrl(bucketName, minioFileName); MinioFile minioFile = new MinioFile(); minioFile.setOriginalFileName(originalFilename); minioFile.setFileExtName(extName); minioFile.setFileName(minioFileName); minioFile.setFileSize(size); minioFile.setMime(contentType); minioFile.setIsDelete(NumberUtils.INTEGER_ZERO); minioFile.setFileUrl(fileUrl); boolean insert = minioFile.insert(); if (insert) { MinioResponseDTO minioResponseDTO = new MinioResponseDTO(); minioResponseDTO.setFileId(minioFile.getId()); minioResponseDTO.setOriginalFileName(originalFilename); minioResponseDTO.setFileUrl(fileUrl); MinioResponseDTOList.add(minioResponseDTO); } } catch (Exception e) { log.error("上传文件出错:{}",e); return ApiResult.error("上传文件出错"); } } return ApiResult.success(MinioResponseDTOList); } @GetMapping("/test") @ApiOperation(value = "测试minio文件上传") public ApiResult testPutObject() throws Exception { FileInputStream fileInputStream = new FileInputStream("C:\\Users\\MSI\\Desktop\\新建文本文档.txt"); boolean bs = minioClientUtils.putObject("fsp-dev", "新建文本文档.txt", fileInputStream, "image/jpg"); log.info("上传成功?"+bs); return ApiResult.success("上传成功"); } }
删除文件:
//文件删除 @DeleteMapping public String delete(String name) { try { MinioClient minioClient = new MinioClient(ENDPOINT, ACCESSKEY, SECRETKEY); minioClient.removeObject(BUCKETNAME, name); } catch (Exception e) { return "删除失败"+e.getMessage(); } return "删除成功"; }
来源地址:https://blog.csdn.net/weixin_59244784/article/details/130246017
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341