Minio简介
MinIO是对象存储服务。
它基于Apache License 开源协议,兼容Amazon S3云存储接口。适合存储非结构化数据,如图片,音频,视频,日志等。
对象文件最大可以达到5TB。
安装
linux
使用二进制文件进行部署
#下载二进制文件
wget https://dl.min.io/server/minio/release/linux-amd64/minio
#添加可执权限
chmod +x minio
#启动minio (/data 为文件存储位置)
./minio server /data
#或者后台指定端口运行
nohup ./minio server --address 172.20.10.10:9002 --console-address 172.20.10.10:9001 /home/minio/data &
#--address minio运行端口
#--console-address minio客户端运行端口
启动一次后会在/data(可自定义文件存储位置)中查看隐藏文件
ll -a
修改配置文件
cd .minio.sys/config/
vim config.json
修改其中的
access_key(用户名)
secret_key(密码)
保存修改后,重启minio即可
项目中使用
配置文件
objectstorage:
min-i-o:
access-key: 账号
secret-key: 密码
endpoint: http://部署地址:部署端口
active: true
path-style-access: false
bucket-name: 桶名称
引入yaml配置文件,创建客户端
@Configuration
public class BeanConfig {
@Value("${objectstorage.min-i-o.endpoint}")
private String endpoint;
@Value("${objectstorage.min-i-o.access-key}")
private String accessKey;
@Value("${objectstorage.min-i-o.secret-key}")
private String secretKey;
/**
* 获取MinIo客户端连接
* */
@Bean
public MinioClient minioClient(){
//构建客户端连接
MinioClient minioClient =
MinioClient.builder()
.endpoint(endpoint)
.credentials(accessKey, secretKey)
.build();
return minioClient;
}
}
封装调用函数
@Service
@Slf4j
public class UploadService {
@Resource
private MinioClient minioClient;
@Value("${objectstorage.min-i-o.endpoint}")
private String endpoint;
@Value("${objectstorage.min-i-o.access-key}")
private String accessKey;
@Value("${objectstorage.min-i-o.secret-key}")
private String secretKey;
/**
* 文件上传
* @return 文件bucket中保存的名称
* */
public String putFile(MultipartFile file, String bucketName) {
checkBucket(bucketName);
InputStream inputStream = null;
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
String originalFilename = file.getOriginalFilename();
String type = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
Random random = new Random();
String fileName = random.nextInt(10000) + System.currentTimeMillis() + "."+ type;
String objectName = getContentType(type) + "/" + (sdf.format(new Date())) +"/" + fileName;
try {
inputStream = file.getInputStream();
} catch (IOException e) {
log.info("文件读取异常 异常 {}",e.getMessage());
}
try {
minioClient.putObject(PutObjectArgs
.builder()
.bucket(bucketName)
.object(objectName)
.stream(
inputStream, -1, 10485760)
.contentType(getContentType(type))
.build());
} catch (Exception e) {
log.info("文件上传异常 异常 {}",e.getMessage());
}
return objectName;
}
/**
* 获取MinIO文件分享链接
* */
public String getShareUrl(String bucketName,String objectName){
String url;
try {
url = minioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(bucketName)
.object(objectName)
.expiry(2, TimeUnit.HOURS)
.build());
}catch (Exception e){
log.error("获取文件分享路径失败 exception -> {}",e.getMessage());
}
return url;
}
/**
* 检查桶是否存在
* */
public void checkBucket(String bucketName){
try {
boolean found =
minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
if(!found){
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 文件删除
* */
@Transactional(rollbackFor = Exception.class)
public void removeFile(String bucketName,String fileUrl){
String objectName = fileUrl.substring(endpoint.length(),fileUrl.length());
try {
minioClient.removeObject(
RemoveObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.build());
} catch (Exception e) {
}
}
/**
* Description: 判断OSS服务文件上传时文件的contentType
*
* @param FilenameExtension 文件后缀
* @return String
*/
public static String getContentType(String FilenameExtension) {
if (FilenameExtension.equalsIgnoreCase("bmp")) {
return "image/bmp";
}
if (FilenameExtension.equalsIgnoreCase("gif")) {
return "image/gif";
}
if (FilenameExtension.equalsIgnoreCase("jpeg") || FilenameExtension.equalsIgnoreCase("jpg")
|| FilenameExtension.equalsIgnoreCase("png")) {
return "image/jpg";
}
if (FilenameExtension.equalsIgnoreCase("html")) {
return "text/html";
}
if (FilenameExtension.equalsIgnoreCase("txt")) {
return "text/plain";
}
if (FilenameExtension.equalsIgnoreCase("vsd")) {
return "application/vnd.visio";
}
if (FilenameExtension.equalsIgnoreCase("pptx") || FilenameExtension.equalsIgnoreCase("ppt")) {
return "application/vnd.ms-powerpoint";
}
if (FilenameExtension.equalsIgnoreCase("docx") || FilenameExtension.equalsIgnoreCase("doc")) {
return "application/msword";
}
if (FilenameExtension.equalsIgnoreCase("xml")) {
return "text/xml";
}
if (FilenameExtension.equalsIgnoreCase("pdf")) {
return "application/pdf";
}
if (FilenameExtension.equalsIgnoreCase("mp4")) {
return "video/mp4";
}
return "image/jpg";
}
/**
* 设置桶的生命周期
* @param days 文件过期时间
* @param filterUrl 文件过滤路径前缀
* @param ruleId 规则名称
* */
public void setBucketLifecycle(Integer days,String filterUrl,String ruleId,String bucketName){
//规则构建
List<LifecycleRule> rules = new LinkedList<>();
rules.add(new LifecycleRule(
Status.ENABLED,
null,
new Expiration((ZonedDateTime) null, days, null),
new RuleFilter(filterUrl),
ruleId,
null,
null,
null)
);
LifecycleConfiguration configuration = new LifecycleConfiguration(rules);
try {
minioClient.setBucketLifecycle(SetBucketLifecycleArgs.builder().bucket(bucketName).config(configuration).build());
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 删除桶的生命周期配置策略
* */
public void deleteLifecycle(String bucketName){
try {
minioClient.deleteBucketLifecycle(
DeleteBucketLifecycleArgs.builder().bucket(bucketName).build());
} catch (Exception e) {
e.printStackTrace();
}
}
}
Controller层引用
@RestController
@RequestMapping("/upload")
@Api(tags = "文件操作")
public class UploadController {
@Resource
private UploadFacade uploadFacade;
@ApiOperation(value = "文件上传" , httpMethod = "POST")
@PostMapping("/upload")
public Result upload(@RequestParam MultipartFile multipartFile){
try {
// 通过ImageReader来解码这个file并返回一个BufferedImage对象
// 如果找不到合适的ImageReader则会返回null,我们可以认为这不是图片文件
// 或者在解析过程中报错,也返回false
MultipartFile files=multipartFile;
String fileName = files.getOriginalFilename();
// 临时文件
File tempFile = new File(System.getProperty("/"), fileName);
FileUtils.copyInputStreamToFile(files.getInputStream(), tempFile);
//files.transferTo(tempFile);
Image image = ImageIO.read((tempFile));
tempFile.delete();
if(image!=null){
return Result.success(uploadFacade.uploadFile(multipartFile));
}else {
return Result.fail("1000","非图片禁止上传");
}
} catch(IOException ex) {
return Result.fail("1001","解析错误");
}
}
@ApiOperation(value = "获取文件访问路径" , httpMethod = "GET")
@GetMapping("/getUrl")
public Result getUrl(@RequestParam String baseUrl){
return Result.success(uploadFacade.getShareUrl(baseUrl));
}
}