一、介绍
开源协议的对象存储服务,轻量,性能强
二、安装
windows版链接: https://pan.baidu.com/s/1vv2p8bZBeZFG9cpIhDLVXQ?pwd=s5dd 提取码: s5dd
下载后创建minioData文件用于储存文件
创建run.bat脚本,内容如下
# 设置用户名
set MINIO_ROOT_USER=admin
# 设置密码(8位)
set MINIO_ROOT_PASSWORD=12345678
minio.exe server --address :9000 --console-address :9001 D:\devtool\minioData
默认账号密码是minioadmin/minioadmin ,编写bat脚本设置启动账号和密码,设置为admin/12345678
启动命令为minio.exe server D:\devtool\minioData
默认参数分别为指定文件访问端口为9000,指定服务控制台访问地址端口为9001
启动bat脚本
访问地址127.0.0.1:9001 账号为admin/12345678
三、操作介绍
1.创建bucket
2.创建账号获取access-key 和secret-key
记录下两个key,在代码中使用
3.图片上传
访问图片的地址为127.0.0.1:9000/test/130253654639.jpg ip+端口+buckets+图片名称
调用地址时,返回没权限访问的提示,需要将bucket设置为public权限
测试访问
四、linux下使用
下载地址链接: https://pan.baidu.com/s/1zUPjLQPhtY5ZjfeRvKp24g?pwd=w2em 提取码: w2em
分别创建储存文件和日志文件,后台启动命令, 其他操作和windows一样
nohup /data/minio/minio server /data/minio/data --address 10.6.49.9:9000 --console-address 10.6.49.9:9001 > /data/minio/logs/log.log 2>&1 &
五、代码中使用
1.配置信息
minio:
endpoint: http://192.168.16.60:9000
accesskey: gzh4Alx3Zm5Eceh2
secretKey: W19q1koRHPhTPWTjulY1Wyvr7b3qAwl7
bucketName: siping
2.配置类
package com.test.mybatistest.minio;
import io.minio.MinioClient;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
/**
* minio配置信息
*/
@Data
@Component
@ConfigurationProperties(prefix = "minio")
public class MinioConfig {
/**
* 服务器地址
*/
private String endpoint;
/**
* 账号
*/
private String accessKey;
/**
* 密码
*/
private String secretKey;
/**
* 储存桶名称
*/
private String bucketName;
@Bean
public MinioClient minioClient() {
return MinioClient.builder()
.endpoint(endpoint)
.credentials(accessKey, secretKey)
.build();
}
}
3.测试类
package com.test.mybatistest.controller;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.github.pagehelper.util.StringUtil;
import com.test.mybatistest.minio.MinioConfig;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
@Api(tags = "Minio")
@RestController
@Slf4j
@RequestMapping("/minio")
public class MinioController {
@Autowired
private MinioClient minioClient;
@Autowired
private MinioConfig minioConfig;
@Value("${minio.bucketName}")
private String bucketName;
/**
* 获取文件后缀
*
* @param fullName
* @return
*/
public static String getFileExtension(String fullName) {
if (StringUtil.isEmpty(fullName)) return StringPool.EMPTY;
String fileName = new File(fullName).getName();
int dotIndex = fileName.lastIndexOf(".");
return (dotIndex == -1) ? "" : fileName.substring(dotIndex + 1);
}
/**
* 文件上传
*
* @param file
* @return
*/
@ApiOperation("文件上传-批量")
@PostMapping("/upload")
public Object upload(@RequestParam(name = "file", required = false) MultipartFile[] file) {
if (file == null || file.length == 0) {
return "上传文件不能为空";
}
List<Map<String, Object>> orgfileNameList = new ArrayList<>(file.length);
for (MultipartFile multipartFile : file) {
//1.名称
String orgfileName = multipartFile.getOriginalFilename();
String fileName = fileName(orgfileName);
String path = minioConfig.getEndpoint() + '/' + bucketName + '/' + fileName;
//2.返回信息
Map<String, Object> fileMap = new HashMap<>();
fileMap.put("orgName", orgfileName);
fileMap.put("fileName", fileName);
fileMap.put("path", path);
orgfileNameList.add(fileMap);
//3.文件上传
try {
InputStream in = multipartFile.getInputStream();
minioClient.putObject(
PutObjectArgs.builder()
.bucket(bucketName)
.object(fileName)
.stream(in, multipartFile.getSize(), -1)
.contentType("application/octet-stream")
.build());
in.close();
} catch (Exception e) {
return "上传失败";
}
}
//4.返回
Map<String, Object> data = new HashMap<>();
data.put("bucket", bucketName);
data.put("fileList", orgfileNameList);
return data;
}
/**
* 生成图片名称
*
* @param originalFilename
* @return
*/
public String fileName(String originalFilename) {
StringBuffer sb = new StringBuffer();
String yyyyMMdd = new SimpleDateFormat("yyyyMMdd").format(new Date());
ThreadLocalRandom random = ThreadLocalRandom.current();
String uuid = new UUID(random.nextLong(), random.nextLong()).toString().replace(StringPool.DASH, StringPool.EMPTY);
sb.append("upload").append("/")
.append(yyyyMMdd).append("/")
.append(uuid).append(".")
.append(getFileExtension(originalFilename));
return sb.toString();
}
}
4.测试
5.contentType作用
当contentType设置为application/octet-stream时,访问文件默认为下载
Content-Type:用于向接收方说明传输资源的媒体类型,从而让浏览器用指定码表去解码。
在浏览器中上传时,设置header为application/octet-stream时,在浏览器打开图片链接会默认进行下载而不是在浏览器中加载打开文件,所以如果想要文件时直接打开,上传时则不要设置application/octet-stream
可以用multipartFile获取contentType,也可以通过文件类型获取
可以通过文件后缀设置对应的contentType
package com.test.mybatistest.minio;
import com.github.pagehelper.util.StringUtil;
/**
* 获取文件的contentType
*/
public enum ViewContentType {
DEFAULT("default", "application/octet-stream"),
JPG("jpg", "image/jpeg"),
TIFF("tiff", "image/tiff"),
GIF("gif", "image/gif"),
JFIF("jfif", "image/jpeg"),
PNG("png", "image/png"),
TIF("tif", "image/tiff"),
ICO("ico", "image/x-icon"),
JPEG("jpeg", "image/jpeg"),
WBMP("wbmp", "image/vnd.wap.wbmp"),
FAX("fax", "image/fax"),
NET("net", "image/pnetvue"),
JPE("jpe", "image/jpeg"),
RP("rp", "image/vnd.rn-realpix"),
DOC("doc", "application/msord"),
PDF("pdf", "application/pdf");
private String prefix;
private String type;
ViewContentType(String prefix, String type) {
this.prefix = prefix;
this.type = type;
}
public static String getContentType(String prefix) {
if (StringUtil.isEmpty(prefix)) {
return DEFAULT.getType();
}
prefix = prefix.substring(prefix.lastIndexOf(".") + 1);
for (ViewContentType value : ViewContentType.values()) {
if (prefix.equalsIgnoreCase(value.getPrefix())) {
return value.getType();
}
}
return DEFAULT.getType();
}
public String getPrefix() {
return prefix;
}
public String getType() {
return type;
}
}