minio是什么
MinIO是一款高性能、分布式的对象存储系统,基于Go语言开发,并且完全兼容Amazon S3云存储服务接口。
MinIO适用于存储大容量非结构化数据,如图片、视频、日志文件、备份数据和容器/虚拟机镜像等。它的一个独特之处在于其简单性和对开发者的友好性,旨在将存储作为一个开发问题而非运维问题。MinIO的设计目标是为云原生应用程序提供高性能、高可用性、可扩展性和安全性的对象存储。它非常适合于各种数据存储场景,包括云备份、容器存储、大数据存储、多媒体存储等。
此外,MinIO是软件定义的,基于Apache License v2.0开源协议,并在GNU AGPL v3下100%开源。它还是Kubernetes的原生产品,是唯一一个可在每个公共云、每个Kubernetes发行版、私有云和边缘上使用的对象存储套件。MinIO以其高性能和可扩展性而著称,可以提供一系列用例,包括AI/ML、分析、备份/恢复以及现代Web和移动应用程序。
windows版本minio的安装与使用
1.下载服务器与客户端
服务器(minio.exe)下载地址minio.exe
客户端(mc.exe)下载地址mc.exe
2.环境安装
- 随便找一个盘新建一个文件夹(文件夹名minio),minio文件夹下新建三个子文件夹分别叫(bin、data、logs)
- 在bin文件夹下将下载的minio.exe和mc.exe放在其下方
- 这里不能直接点击minio.exe进行启动服务器,需要通过命令框进行打开
- 用管理员身份打开cmd,执行下面的命令
e: #切换盘符
cd E:\minio\bin #打开minio.exe所在的文件地址
setx MINIO_ROOT_USER name #name改为想设置的用户名
setx MINIO_ROOT_PASSWORD password #password改为想设置登录密码
minio.exe server E:\minio\data --console-address ":9990" #启动服务器(E:\minio\data 为存储数据的地址) (":9990" 为客户端的端口 )
登录后的效果
- 这里我为了方便写了一个bat脚本用于快速启动服务器和客户端
建一个以".bat"结尾的文件,用txt打开写入下面的文本(删一下打的注释(#和他后面的文本))
@echo off
echo.
echo [信息] 运行MinIO文服务器。
echo.
title minio
cd %~dp0
cd E:\minio\bin #minio.exe所在的文件地址
#启动服务器(E:\minio\data 为存储数据的地址) (":9990" 为客户端的端口 )
minio.exe server E:\minio\data --console-address ":9990"
pause
- 保存后双击打开即可快速启动
3.桶的创建与设置
- 打开客户端网址
- 登录进去后点击Bucket->Create Bucket->输入桶名->创建桶
- 桶的权限设置(通过点击桶,进入该桶的详细设置)
- 将桶的权限改为public
4.Java的使用代码
- meven导包
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.8.1</version>
</dependency>
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.5.6</version>
</dependency>
- minio代码(该代码是通过aplication.yml获取minio信息,本地获取文件)
- aplication.yml
minio:
config:
url: http://10.69.0.76:9000 #接口地址(API地址)
accessKey: admin #用户名
secretKey: admin123456 #用户密码
bucketName: chen-buck #桶名(也可以通过传参的形式传桶名,将不同的文件放入不同的桶中)
- minio上传,下载代码
- minio官方API文档
import io.minio.*;
import io.minio.errors.MinioException;
import io.minio.http.Method;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@Service
public class MinioUtil{
//yml注入
/**
* 服务地址
*/
@Value("$minio.config.url")
private String url;
/**
* 用户名
*/
@Value("$minio.config.accessKey")
private String accessKey;
/**
* 密码
*/
@Value("$minio.config.secretKey")
private String secretKey;
/**
* 存储桶名称
*/
@Value("$minio.config.bucketName")
private String bucketName;
public String upload(String file) throws Exception {
try {
// 创建MinioClient用于访问桶
MinioClient minioClient =
MinioClient.builder()
//桶地址
.endpoint(url)
//用户名,密码
.credentials(accessKey, secretKey)
.build();
// 是否存在该桶
boolean found =
minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
if (!found) {
//创建一个新的桶
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
} else {
System.out.println("Bucket "+bucketName+" already exists.");
}
//存储的文件名用UUID生成随机数进行命名
String name=UUID.randomUUID().toString();
//因为存入的文件修改了文件名,所以通过该方式拼接文件后缀
String[] split = file.split("\\\\");
name=name+"."+split[split.length-1].split("\\.")[1];
//上传文件到仓库
minioClient.uploadObject(
UploadObjectArgs.builder()
.bucket(bucketName)
.object(name)
.filename(path)
.build());
System.out.println(
file+" is successfully uploaded as "
+ "object"+name+" to bucket"+bucketName);
//获取文件在桶中的url
String url = minioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.PUT)
.bucket(bucketName)//桶名
.object(name)//文件名
.expiry(1, TimeUnit.DAYS) // 一天过期时间,默认是7天
.build());
//输出地址到控制台
System.out.println("url:"+url.split("\\?")[0]);
//返回地址给调用者
return url.split("\\?")[0];
} catch (MinioException e) {
System.out.println("Error occurred: " + e);
System.out.println("HTTP trace: " + e.httpTrace());
}
return "";
}
//仓库获取文件
public InputStream downFile(String bucketName,String filename) {
// 创建MinioClient用于访问桶
MinioClient minioClient =
MinioClient.builder()
.endpoint(minioConfig.getUrl())
.credentials(minioConfig.getAccessKey(), minioConfig.getSecretKey())
.build();
try {
InputStream stream = minioClient.getObject(
GetObjectArgs.builder()
.bucket(bucketName)
.object(filename)
.build());
return stream;
} catch (Exception ex) {
System.out.println(ex);
return null;
}
}
- 上传文件存储本地的工具类文件MultipartFileToFileUtils
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.util.UUID;
public class MultipartFileToFileUtils {
/**
* @param file
* @param targetDirPath 存储MultipartFile文件的目标文件夹
* @return 文件的存储的绝对路径
*/
public static String saveMultipartFile(MultipartFile file, String targetDirPath) {
File toFile = null;
if (file.equals("") || file.getSize() <= 0) {
return null;
} else {
/*获取文件原名称*/
String originalFilename = file.getOriginalFilename();
/*获取文件格式*/
String fileFormat = originalFilename.substring(originalFilename.lastIndexOf("."));
String uuid = UUID.randomUUID().toString().trim().replaceAll("-", "");
toFile = new File(targetDirPath + File.separator +uuid+"-"+ originalFilename);
String absolutePath = null;
try {
absolutePath = toFile.getCanonicalPath();
/*判断路径中的文件夹是否存在,如果不存在,先创建文件夹*/
String dirPath = absolutePath.substring(0, absolutePath.lastIndexOf(File.separator));
File dir = new File(dirPath);
if (!dir.exists()) {
dir.mkdirs();
}
InputStream ins = file.getInputStream();
inputStreamToFile(ins, toFile);
ins.close();
} catch (IOException e) {
e.printStackTrace();
}
return absolutePath;
}
}
//获取流文件
private static void inputStreamToFile(InputStream ins, File file) {
try {
OutputStream os = new FileOutputStream(file);
int bytesRead = 0;
byte[] buffer = new byte[8192];
while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
os.write(buffer, 0, bytesRead);
}
os.close();
ins.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 删除本地临时文件
*
* @param file
*/
public static void deleteTempFile(File file) {
if (file != null) {
File del = new File(file.toURI());
del.delete();
}
}
}
- controller层代码
import com.wedu.common.utils.R;
import com.wedu.modules.fileCunChu.*;
import com.wedu.modules.sys.controller.AbstractController;
import com.wedu.utils.MultipartFileToFileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@RestController
@RequestMapping("/excle")
public class ExcleUpOrDoController extends AbstractController {
@Autowired
private MinioUtil minioUtil;
// 文件导入
@PostMapping("/getfile")
public R uplodeMinio(@RequestPart("file")MultipartFile file) throws Exception {
//将文件存储到本地
String s = MultipartFileToFileUtils.saveMultipartFile(file, "E:\\ruanjianlishiwenjian\\two\\");
//调用minio的上传方法
String upload = minioUtil.upload(s);
return R.ok().put("url",upload);
}
//文件下载
@GetMapping("/downfile")
public void uplodeMinio(@RequestParam("fileUrl") String fileUrl, HttpServletResponse response) throws Exception {
try {
String url = fileUrl.split(":9000/")[1];
String[] path = url.split("/");
//获取桶名
String bucketName=path[0];
// 拿到文件名
String filename=path[path.length-1];
// 获取文件对象
InputStream object = uploadService.downFile(bucketName,filename);
byte buf[] = new byte[1024];
int length = 0;
response.reset();
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(url.substring(url.lastIndexOf("/") + 1), "UTF-8"));
response.setContentType("application/octet-stream");
response.setCharacterEncoding("UTF-8");
OutputStream outputStream = response.getOutputStream();
// 输出文件
while ((length = object.read(buf)) > 0) {
outputStream.write(buf, 0, length);
}
// 关闭输出流
outputStream.close();
} catch (Exception ex) {
response.setHeader("Content-type", "text/html;charset=UTF-8");
String data = "文件下载失败";
OutputStream ps = response.getOutputStream();
ps.write(data.getBytes("UTF-8"));
}
}
}
- 测试
- 文件传入
登入rul会得到图片
- 文件下载