赞
踩
Minio
官网地址:https://min.io/
文档地址:https://docs.min.io/
Minio
是一款开源的对象存储服务器,它可以运行在多种操作系统上,包括Linux、Windows和MacOS
等。它提供了一种简单、可扩展、高可用的对象存储解决方案,支持多种数据格式,包括对象、块和文件等。
Minio
的主要特点:
Minio
的安装和配置非常简单,只需要下载并运行相应的二进制文件即可。它提供了一个Web UI,可以通过界面管理存储桶和对象。Minio
还支持块存储,允许用户上传和下载大型文件(例如图像或视频)。块存储是一种快速、高效的方式来处理大型文件。总之,Minio是一款强大、灵活、可扩展的对象存储服务器,适用于各种应用场景,包括云存储、大数据存储和物联网等。
MinIO是一种高性能、扩展性好的对象存储系统,它可以适用于许多应用场景,其中包括但不限于以下几种:
需要注意的是,以上列出的应用场景并不是MinIO所有可适用的场景。具体取决于每个使用情况的细节和需求。
使用SpringBoot和MinIO
实现分片上传、秒传、续传主要包含以下几个步骤:
总体而言,使用SpringBoot和MinIO实现分片上传、秒传、续传的难度不算大,可以根据上述步骤进行开发和实现。
创建目标文件夹:mkdir minio
使用docker查看目标镜像状况:docker search minio
使用docker拉去镜像:docker pull minio/minio
查看镜像是否拉取成功:docker images
启动Minio容器
docker run
-p 9000:9000 -p 9090:9090
--net=host
--name minio
-d --restart=always
-e "MINIO_ACCESS_KEY=IT@test"
-e "MINIO_SECRET_KEY=IT@test"
minio/minio server /data --console-address ":9000"
-address ":9090"
注意一下,对于密码强度是有要求的,不然报错
这是一个运行 MinIO 容器的 Docker 命令,具体参数解释如下:
-p
:映射容器内部的端口到宿主机上。其中 9000 和 9090 分别映射到宿主机的 9000 和 9090 端口上。冒号前是宿主机端口,后是容器端口--net=host
:将容器加入到主机网络中,共享宿主机的 IP 地址。--name minio
:指定容器的名称为 minio。--restart=always
:设置容器在退出后自动重新启动。-e
:设置环境变量。这里设置了两个环境变量:MINIO_ACCESS_KEY 和 MINIO_SECRET_KEY,值分别为 IT@test和 IT@test。--mount
:将容器内部的目录挂载到宿主机上。这里将容器内的 /data 目录挂载到了宿主机的 /data 目录上。--console-address
:指定容器的控制台地址。这里设置为 :9000,表示可以通过宿主机上的 9000 端口访问容器的控制台。-address
:指定容器的网络地址。这里设置为 :9090,表示可以通过宿主机上的 9090 端口访问容器的服务。提示:页面访问9000,代码里面9090
用户名密码就是启动参数里面的数据
如果访问失败,那就是防火墙问题或者是启动参数最后两项没有添加,再不会有其他的,除非容器没有启动成功
查看放行端口可以使用如下命令:firewall-cmd --list-ports
要放行CentOS 7上的9000端口和9090端口,可以按照以下步骤操作:
检查防火墙状态
使用以下命令检查防火墙状态:systemctl status firewalld
如果防火墙已停止,则启动它:systemctl start firewalld
允许9000端口通过防火墙
使用以下命令允许TCP流量通过9000端口:
firewall-cmd --zone=public --add-port=9000/tcp --permanent
firewall-cmd --zone=public --add-port=9090/tcp --permanent
这将向防火墙添加一个规则,以允许TCP流量通过9000端口。要永久保存此更改,请运行以下命令:firewall-cmd --reload
重新启动防火墙服务shell
使用以下命令重新启动防火墙服务:systemctl restart firewalld
<!-- 操作minio的java客户端--> <dependency> <groupId>io.minio</groupId> <artifactId>minio</artifactId> <version>8.5.2</version> </dependency> <!-- jwt鉴权相应依赖--> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-jackson</artifactId> <version>0.11.2</version> </dependency>
获取API访问凭证
server:
port: 8080
spring:
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
#minio配置
minio:
access-key: dAMaxkWaXUD1CV1JHbqw
secret-key: AXt3SD0JFkDENFbMeJKOOQb5wj8KvabZWu33Rs84
url: http://127.0.0.1:9090 #访问地址
bucket-name: wanghui
首先是服务器的配置:
multipart/form-data
类型的请求。接下来是minio的配置:
bucket-name
是存储文件的桶名,需要根据实际情况进行填写。http请求状态
public class HttpStatus { /** * 操作成功 */ public static final int SUCCESS = 200; /** * 对象创建成功 */ public static final int CREATED = 201; /** * 请求已经被接受 */ public static final int ACCEPTED = 202; /** * 操作已经执行成功,但是没有返回数据 */ public static final int NO_CONTENT = 204; /** * 资源已被移除 */ public static final int MOVED_PERM = 301; /** * 重定向 */ public static final int SEE_OTHER = 303; /** * 资源没有被修改 */ public static final int NOT_MODIFIED = 304; /** * 参数列表错误(缺少,格式不匹配) */ public static final int BAD_REQUEST = 400; /** * 未授权 */ public static final int UNAUTHORIZED = 401; /** * 访问受限,授权过期 */ public static final int FORBIDDEN = 403; /** * 资源,服务未找到 */ public static final int NOT_FOUND = 404; /** * 不允许的http方法 */ public static final int BAD_METHOD = 405; /** * 资源冲突,或者资源被锁 */ public static final int CONFLICT = 409; /** * 不支持的数据,媒体类型 */ public static final int UNSUPPORTED_TYPE = 415; /** * 系统内部错误 */ public static final int ERROR = 500; /** * 接口未实现 */ public static final int NOT_IMPLEMENTED = 501; /** * 系统警告消息 */ public static final int WARN = 601; }
通用常量信息
import io.jsonwebtoken.Claims; public class Constants { /** * UTF-8 字符集 */ public static final String UTF8 = "UTF-8"; /** * GBK 字符集 */ public static final String GBK = "GBK"; /** * www主域 */ public static final String WWW = "www."; /** * http请求 */ public static final String HTTP = "http://"; /** * https请求 */ public static final String HTTPS = "https://"; /** * 通用成功标识 */ public static final String SUCCESS = "0"; /** * 通用失败标识 */ public static final String FAIL = "1"; /** * 登录成功 */ public static final String LOGIN_SUCCESS = "Success"; /** * 注销 */ public static final String LOGOUT = "Logout"; /** * 注册 */ public static final String REGISTER = "Register"; /** * 登录失败 */ public static final String LOGIN_FAIL = "Error"; /** * 验证码有效期(分钟) */ public static final Integer CAPTCHA_EXPIRATION = 2; /** * 令牌 */ public static final String TOKEN = "token"; /** * 令牌前缀 */ public static final String TOKEN_PREFIX = "Bearer "; /** * 令牌前缀 */ public static final String LOGIN_USER_KEY = "login_user_key"; /** * 用户ID */ public static final String JWT_USERID = "userid"; /** * 用户名称 */ public static final String JWT_USERNAME = Claims.SUBJECT; /** * 用户头像 */ public static final String JWT_AVATAR = "avatar"; /** * 创建时间 */ public static final String JWT_CREATED = "created"; /** * 用户权限 */ public static final String JWT_AUTHORITIES = "authorities"; /** * 资源映射路径 前缀 */ public static final String RESOURCE_PREFIX = "/profile"; /** * RMI 远程方法调用 */ public static final String LOOKUP_RMI = "rmi:"; /** * LDAP 远程方法调用 */ public static final String LOOKUP_LDAP = "ldap:"; /** * LDAPS 远程方法调用 */ public static final String LOOKUP_LDAPS = "ldaps:"; /** * 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加) */ public static final String[] JOB_WHITELIST_STR = { "com.ruoyi" }; /** * 定时任务违规的字符 */ public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml", "org.springframework", "org.apache", "com.ruoyi.common.utils.file", "com.ruoyi.common.config" }; }
import io.minio.MinioClient; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Data @Configuration @ConfigurationProperties(prefix = "spring.minio") public class MinioConfig { private String accessKey; private String secretKey; private String url; private String bucketName; @Bean public MinioClient minioClient(){ return MinioClient.builder() .endpoint(url) .credentials(accessKey,secretKey) .build(); } }
这段代码是Java中的一个配置类,用于配置与MinIO(一个对象存储服务)相关的属性。
minioClient()
方法返回了一个MinioClient
对象,用于连接到MinIO服务并操作存储桶。其中,endpoint()
方法用于设置MinIO服务的URL地址,credentials()
方法用于设置访问密钥和密钥值。
import io.minio.*; import io.minio.errors.*; import io.minio.http.Method; import lombok.SneakyThrows; import org.apache.tomcat.util.http.fileupload.IOUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.time.ZonedDateTime; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; @Component public class MinioUtils { @Autowired private MinioClient minioClient; @Autowired private MinioConfig configuration; /** * @param name 名字 * @return boolean * @Description description: 判断bucket是否存在,不存在则创建 */ public boolean existBucket(String name) { boolean exists; try { exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(name).build()); if (!exists) { minioClient.makeBucket(MakeBucketArgs.builder().bucket(name).build()); exists = true; } } catch (Exception e) { e.printStackTrace(); exists = false; } return exists; } /** * @param bucketName 存储bucket名称 * @return {@link Boolean } * @Description 创建存储bucket */ public Boolean makeBucket(String bucketName) { try { minioClient.makeBucket(MakeBucketArgs.builder() .bucket(bucketName) .build()); } catch (Exception e) { e.printStackTrace(); return false; } return true; } /** * @param bucketName 存储bucket名称 * @return {@link Boolean } * @Description 删除存储bucket */ public Boolean removeBucket(String bucketName) { try { minioClient.removeBucket(RemoveBucketArgs.builder() .bucket(bucketName) .build()); } catch (Exception e) { e.printStackTrace(); return false; } return true; } /** * @param fileName 文件名称 * @param time 时间 * @return {@link Map } * @Description 获取上传临时签名 */ @SneakyThrows public Map getPolicy(String fileName, ZonedDateTime time) { PostPolicy postPolicy = new PostPolicy(configuration.getBucketName(), time); postPolicy.addEqualsCondition("key", fileName); try { Map<String, String> map = minioClient.getPresignedPostFormData(postPolicy); HashMap<String, String> map1 = new HashMap<>(); map.forEach((k, v) -> { map1.put(k.replaceAll("-", ""), v); }); map1.put("host", configuration.getUrl() + "/" + configuration.getBucketName()); return map1; } catch (ErrorResponseException e) { e.printStackTrace(); } catch (InsufficientDataException e) { e.printStackTrace(); } catch (InternalException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (InvalidResponseException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (ServerException e) { e.printStackTrace(); } catch (XmlParserException e) { e.printStackTrace(); } return null; } /** * @param objectName 对象名称 * @param method 方法 * @param time 时间 * @param timeUnit 时间单位 * @return {@link String } * @Description 获取上传文件的url */ public String getPolicyUrl(String objectName, Method method, int time, TimeUnit timeUnit) { try { return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder() .method(method) .bucket(configuration.getBucketName()) .object(objectName) .expiry(time, timeUnit).build()); } catch (ErrorResponseException e) { e.printStackTrace(); } catch (InsufficientDataException e) { e.printStackTrace(); } catch (InternalException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (InvalidResponseException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (XmlParserException e) { e.printStackTrace(); } catch (ServerException e) { e.printStackTrace(); } return null; } /** * @param file 文件 * @param fileName 文件名称 * @Description 上传文件 */ public void upload(MultipartFile file, String fileName) { // 使用putObject上传一个文件到存储桶中。 try { InputStream inputStream = file.getInputStream(); minioClient.putObject(PutObjectArgs.builder() .bucket(configuration.getBucketName()) .object(fileName) .stream(inputStream, file.getSize(), -1) .contentType(file.getContentType()) .build()); } catch (ErrorResponseException e) { e.printStackTrace(); } catch (InsufficientDataException e) { e.printStackTrace(); } catch (InternalException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (InvalidResponseException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (ServerException e) { e.printStackTrace(); } catch (XmlParserException e) { e.printStackTrace(); } } /** * @param objectName 对象名称 * @param time 时间 * @param timeUnit 时间单位 * @return {@link String } * @Description 根据filename获取文件访问地址 */ public String getUrl(String objectName, int time, TimeUnit timeUnit) { String url = null; try { url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder() .method(Method.GET) .bucket(configuration.getBucketName()) .object(objectName) .expiry(time, timeUnit).build()); } catch (ErrorResponseException e) { e.printStackTrace(); } catch (InsufficientDataException e) { e.printStackTrace(); } catch (InternalException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (InvalidResponseException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (XmlParserException e) { e.printStackTrace(); } catch (ServerException e) { e.printStackTrace(); } return url; } /** * @param fileName * @return {@link ResponseEntity }<{@link byte[] }> * @Description description: 下载文件 */ public ResponseEntity<byte[]> download(String fileName) { ResponseEntity<byte[]> responseEntity = null; InputStream in = null; ByteArrayOutputStream out = null; try { in = minioClient.getObject(GetObjectArgs.builder().bucket(configuration.getBucketName()).object(fileName).build()); out = new ByteArrayOutputStream(); IOUtils.copy(in, out); //封装返回值 byte[] bytes = out.toByteArray(); HttpHeaders headers = new HttpHeaders(); try { headers.add("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } headers.setContentLength(bytes.length); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); headers.setAccessControlExposeHeaders(Arrays.asList("*")); responseEntity = new ResponseEntity<byte[]>(bytes, headers, HttpStatus.SUCCESS); } catch (Exception e) { e.printStackTrace(); } finally { try { if (in != null) { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } if (out != null) { out.close(); } } catch (IOException e) { e.printStackTrace(); } } return responseEntity; } /** * @param objectFile 对象文件 * @return {@link String } * @Description 根据文件名和桶获取文件路径 */ public String getFileUrl(String objectFile) { try { return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder() .method(Method.GET) .bucket(configuration.getBucketName()) .object(objectFile) .build() ); } catch (Exception e) { e.printStackTrace(); } return null; } }
该代码是一个工具类,用于使用阿里云的对象存储服务(OSS)进行文件上传和下载。具体功能如下:
public class AjaxResult extends HashMap<String, Object> { private static final long serialVersionUID = 1L; /** 状态码 */ public static final String CODE_TAG = "code"; /** 返回内容 */ public static final String MSG_TAG = "msg"; /** 数据对象 */ public static final String DATA_TAG = "data"; /** * 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。 */ public AjaxResult() { } /** * 初始化一个新创建的 AjaxResult 对象 * * @param code 状态码 * @param msg 返回内容 */ public AjaxResult(int code, String msg) { super.put(CODE_TAG, code); super.put(MSG_TAG, msg); } /** * 初始化一个新创建的 AjaxResult 对象 * * @param code 状态码 * @param msg 返回内容 * @param data 数据对象 */ public AjaxResult(int code, String msg, Object data) { super.put(CODE_TAG, code); super.put(MSG_TAG, msg); if (data!=null) { super.put(DATA_TAG, data); } } /** * 返回成功消息 * * @return 成功消息 */ public static AjaxResult success() { return AjaxResult.success("操作成功"); } /** * 返回成功数据 * * @return 成功消息 */ public static AjaxResult success(Object data) { return AjaxResult.success("操作成功", data); } /** * 返回成功消息 * * @param msg 返回内容 * @return 成功消息 */ public static AjaxResult success(String msg) { return AjaxResult.success(msg, null); } /** * 返回成功消息 * * @param msg 返回内容 * @param data 数据对象 * @return 成功消息 */ public static AjaxResult success(String msg, Object data) { return new AjaxResult(HttpStatus.SUCCESS, msg, data); } /** * 返回警告消息 * * @param msg 返回内容 * @return 警告消息 */ public static AjaxResult warn(String msg) { return AjaxResult.warn(msg, null); } /** * 返回警告消息 * * @param msg 返回内容 * @param data 数据对象 * @return 警告消息 */ public static AjaxResult warn(String msg, Object data) { return new AjaxResult(HttpStatus.WARN, msg, data); } /** * 返回错误消息 * * @return 错误消息 */ public static AjaxResult error() { return AjaxResult.error("操作失败"); } /** * 返回错误消息 * * @param msg 返回内容 * @return 错误消息 */ public static AjaxResult error(String msg) { return AjaxResult.error(msg, null); } /** * 返回错误消息 * * @param msg 返回内容 * @param data 数据对象 * @return 错误消息 */ public static AjaxResult error(String msg, Object data) { return new AjaxResult(HttpStatus.ERROR, msg, data); } /** * 返回错误消息 * * @param code 状态码 * @param msg 返回内容 * @return 错误消息 */ public static AjaxResult error(int code, String msg) { return new AjaxResult(code, msg, null); } /** * 方便链式调用 * * @param key 键 * @param value 值 * @return 数据对象 */ @Override public AjaxResult put(String key, Object value) { super.put(key, value); return this; } }
import com.xiaohui.utils.AjaxResult; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.util.HashMap; /** * @Description minio文件上传控制器 */ @CrossOrigin @RestController @RequestMapping("/api") public class MinioFileUploadController { @Autowired private MinioUtils minioUtils; /** * @param file 文件 * @param fileName 文件名称 * @return {@link AjaxResult } * @Description 上传文件 */ @GetMapping("/upload") public AjaxResult uploadFile(@RequestParam("file") MultipartFile file, String fileName) { minioUtils.upload(file, fileName); return AjaxResult.success("上传成功"); } /** * @param fileName 文件名称 * @return {@link ResponseEntity } * @Description dowload文件 */ @GetMapping("/dowload") public ResponseEntity dowloadFile(@RequestParam("fileName") String fileName) { return minioUtils.download(fileName); } /** * @param fileName 文件名称 * @return {@link AjaxResult } * @Description 得到文件url */ @GetMapping("/getUrl") public AjaxResult getFileUrl(@RequestParam("fileName") String fileName){ HashMap map=new HashMap(); map.put("FileUrl",minioUtils.getFileUrl(fileName)); return AjaxResult.success(map); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。