一、版本选择
直到笔者写这篇文章的时候Minio-API已经出到了8.x,我试用过,发现8.x版本的API主要的改动就是把零散的一些入参,整合成了一个个对象。经过对比,我发现还是7.x的简单易懂,如果小伙伴用的是8.x版本的Minio-API那么不建议你看第三步,因为我的方法已经不适用了。
二、Minio服务器搭建
2.1 下载
因为Docker下载安装启动各种中间件过于简单和方便,所以此处只介绍手动下载。
Minio官方下载地址:http://www.minio.org.cn/download.shtml#/,只需要下载服务器即可。
2.2 启动
Minio官方文档:http://docs.minio.org.cn/docs/,因为不同的系统启动指令不同,所以可以参考官方的启动文档,里面还算详细。
2.3 访问
成功启动后,可以看到如图的提示:
这里的minioadmin是指的账号和密码,此时我们访问http://127.0.0.1:9000,即可成功访问到Minio管理端可视化界面。
界面如图:
- Buckets:翻译过来就是“桶”,它主要是用来管理我们文件服务器有多少个“桶”的,“桶”可以理解为一个文件夹,里面是用来存放文件的。
- Identity:用来管理用户和账号。
- Access:用来控制一些权限。
- Monitoring:用来监控一些文件服务器的指标,如桶的数量、文件大小、一些日志等。
- Support:Minio服务器提供的一些额外支持功能。
- License:Minio服务器的许可证和支持计划(付费买更高级的服务)。
- Settings:Minio服务器设置相关。
- Documentation:Minio的一些官方文档。
三、SpringBoot集成Minio-API
3.1 导入依赖
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>7.0.2</version>
</dependency>
3.2 添加配置
配置文件:
minio:
url: http://127.0.0.1:9000
endpoint: http://127.0.0.1:9000
access-key: minioadmin
secret-key: minioadmin
bucket-name: study
test-folder: test
配置类 MinioProperties:
/**
* @description: Minio文件配置
* @author: Felix.Du
* @date: 2022/4/11 3:38 下午
*/
@Data
@ConfigurationProperties(prefix = "minio")
@Component
public class MinioProperties {
/**
* minio 服务地址 http://ip:port
*/
private String url;
/**
* minio 服务地址对外访问地址
*/
private String endpoint;
/**
* accessKey
*/
private String accessKey;
/**
* 密码
*/
private String secretKey;
/**
* 桶名称
*/
private String bucketName;
/**
* 下载文件夹名称
*/
private String testFolder;
}
配置类 MinioConfiguration:
/**
* @description: MinioClient配置Bean
* @author: Felix.Du
* @date: 2022/4/11 5:38 下午
*/
@Configuration
@Slf4j
public class MinioConfiguration {
@Bean
MinioClient minioClient(MinioProperties properties) {
try {
return new MinioClient(
properties.getUrl(),
properties.getAccessKey(), properties.getSecretKey()
);
} catch (Exception e) {
log.error("初始化MinioClient失败", e);
return null;
}
}
}
3.3 工具类
OssUtils:
public class OssUtils {
private static Map<String, String> map = new HashMap<>(){{
put(".bmp", "image/bmp");
put(".webp", "image/webp");
put(".gif", "image/gif");
put(".jpeg", "image/jpeg");
put(".jpg", "image/jpg");
put(".png", "image/png");
put(".html", "text/html");
put(".txt", "text/plain");
put(".vsd", "application/vnd.visio");
put(".ppt", "application/vnd.ms-powerpoint");
put(".pptx", "application/vnd.ms-powerpoint");
put(".doc", "application/msword");
put(".docx", "application/msword");
put(".xml", "text/xml");
put(".mp4", "video/mp4");
put(".mp3", "audio/mp3");
}};
private static FileNameMap fileNameMap = URLConnection.getFileNameMap();
public static String getContentType(String fileName) {
int index = fileName.lastIndexOf(".");
if (index == -1) {
return "application/octet-stream";
}
String fileExtension = fileName.substring(index);
String type = fileNameMap.getContentTypeFor(fileExtension);
if (Objects.isNull(type)) {
type = map.get(fileExtension);
}
if (Objects.isNull(type)) {
return "application/octet-stream";
}
return type;
}
}
3.4 具体实现
MinioStorageService:
/**
* @description: Minio文件存储服务
* @author: Felix.Du
* @date: 2022/4/11 3:38 下午
*/
public interface MinioStorageService {
/**
* 上传文件
*
* @param file 文件
* @return
*/
String upload(MultipartFile file);
/**
* 根据文件url删除普通文件
*
* @param fileUrl 文件url链接
* @return 1->删除成功,0->删除失败
*/
Integer deleteFile(String fileUrl);
/**
* 批量上传文件
*
* @param fileList 文件list
* @return
*/
List<String> uploadBatchFile(List<MultipartFile> fileList);
/**
* 检查文件存储桶是否存在
*
* @param bucketName bucket桶名称
* @return true->存在,false->不存在
*/
boolean bucketExists(String bucketName);
/**
* 创建bucket
*
* @param bucketName bucket桶名称
*/
void createBucket(String bucketName);
/**
* 获取所有bucket
*
* @return bucket 列表
*/
List<BucketVO> getAllBuckets();
}
MinioStorageServiceImpl:
/**
* @description: Minio文件存储服务
* @author: Felix.Du
* @date: 2022/4/11 3:38 下午
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class MinioStorageServiceImpl implements MinioStorageService {
private final MinioClient minioClient;
private final MinioProperties minioProperties;
@Override
public String upload(MultipartFile file) {
return uploadFile(file);
}
@Override
public boolean bucketExists(String bucketName) {
try {
return minioClient.bucketExists(bucketName);
} catch (Exception e) {
log.error("检查文件存储桶是否存在出错", e);
}
return false;
}
@Override
public void createBucket(String bucketName) {
try {
minioClient.makeBucket(bucketName);
} catch (Exception e) {
log.error("创建bucket出错", e);
}
}
@Override
public Integer deleteFile(String fileUrl) {
try {
if (checkFileName(fileUrl)) {
minioClient.removeObject(
minioProperties.getBucketName(),
minioProperties.getTestFolder() + fileUrl.substring(fileUrl.lastIndexOf("/"))
);
return 1;
} else {
log.error("删除文件失败,无效的文件url");
}
} catch (Exception e) {
log.error("删除文件出错", e);
}
return 0;
}
@Override
public List<String> uploadBatchFile(List<MultipartFile> fileList) {
List<String> urlList = new ArrayList<>();
fileList.forEach(file -> urlList.add(uploadFile(file)));
return urlList;
}
@Override
public List<BucketVO> getAllBuckets() {
try {
List<Bucket> buckets = minioClient.listBuckets();
List<BucketVO> bucketVos = new ArrayList<>();
if (buckets != null && !buckets.isEmpty()) {
buckets.forEach(bucket -> {
BucketVO bucketVO = new BucketVO();
BeanUtils.copyProperties(bucket, bucketVO);
bucketVO.setCreateTime(bucket.creationDate().toLocalDateTime());
bucketVos.add(bucketVO);
});
}
return bucketVos;
} catch (Exception e) {
log.error("获取所有bucket出错", e);
return Collections.emptyList();
}
}
private String replaceEndpoint(String url) {
return url.replace(minioProperties.getUrl(), minioProperties.getEndpoint());
}
/**
* 校验文件名是否合法
*
* @return true->合法,false->不合法
*/
private boolean checkFileName(String fileUrl) {
return !StringUtils.isEmpty(fileUrl) && fileUrl.contains("/");
}
private String uploadFile(MultipartFile file) {
try (InputStream is = file.getInputStream()) {
String originName = file.getOriginalFilename(),
contentType = file.getContentType();
assert originName != null;
if (Objects.isNull(contentType)) {
contentType = OssUtils.getContentType(originName);
}
int index = originName.lastIndexOf(".");
var fileName = UUID.randomUUID().toString();
if (index != -1) {
String fileExtension = originName.substring(index);
fileName = fileName + fileExtension;
}
var options = new PutObjectOptions(file.getSize(), -1);
options.setContentType(contentType);
minioClient.putObject(minioProperties.getBucketName(), minioProperties.getTestFolder() + File.separator + fileName, is, options);
return replaceEndpoint(minioClient.getObjectUrl(minioProperties.getBucketName(), minioProperties.getTestFolder() + File.separator + fileName));
} catch (Exception e) {
if (log.isErrorEnabled()) {
log.error("上传文件出现错误", e);
}
}
return null;
}
}
控制层 MinioStorageController:
/**
* @description: Minio文件存储服务
* @author: Felix.Du
* @date: 2022/4/11 5:38 下午
*/
@Slf4j
@RestController
@RequiredArgsConstructor
public class MinioStorageController {
private final MinioStorageService minioStorageService;
@PostMapping("/upload")
public String upload(MultipartFile file) {
return minioStorageService.upload(file);
}
@GetMapping("/bucketExists")
public boolean bucketExists(@RequestParam String bucketName) {
return minioStorageService.bucketExists(bucketName);
}
@PostMapping("/createBucket")
public void createBucket(String bucketName) {
minioStorageService.createBucket(bucketName);
}
@DeleteMapping("/deleteFile")
public Integer deleteFile(String fileUrl) {
return minioStorageService.deleteFile(fileUrl);
}
@PostMapping("/uploadBatchFile")
public List<String> uploadBatchFile(@RequestPart("file") MultipartFile[] files) {
return minioStorageService.uploadBatchFile(Arrays.stream(files).collect(Collectors.toList()));
}
@GetMapping("/getAllBuckets")
public List<BucketVO> getAllBuckets() {
return minioStorageService.getAllBuckets();
}
}
注意:上传文件成功后返回的url,如果输入浏览器无法直接打开,是因为没有将该“桶”的权限放开。点击左侧的“Buckets” -> “Manage” -> “Access Policy”,将“private”修改为“public”即可。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/67256.html