SpringBoot整合Minio实现上传文件的完整步骤记录

网友投稿 401 2022-07-28


目录Minio安装 Minio使用docker安装拉取镜像启动使用9000端口 登录控制台创建存储桶设置桶权限创建 java 客户端依赖配置文件配置文件配置类创建 minio 客户端文件地址返回路径实体类上传文件工具类测试上传文件 Controller测试上传控制台也可以看到上传的视频总结

Minio

上传文件如果不使用云服务的话,需要本地搭建,一般选择 FastDFS 但是 FastDFS 安装比较复杂,今天了解一款安装使用更简单的存储系统 MinIO

MinIO 是一款高性能、分布式的对象存储系统. 它是一款软件产品, 可以100%的运行在标准硬件。即X86等低成本机器也能够很好的运行MinIO。

MinIO与传统的存储和其他的对象存储不同的是:它一开始就针对性能要求更高的私有云标准进行软件架构设计。因为MinIO一开始就只为对象存储而设计。所以他采用了更易用的方式进行设计,它能实现对象存储所需要的全部功能,在性能上也更加强劲,它不会为了更多的业务功能而妥协,失去MinIO的易用性、高效性。 这样的结果所带来的好处是:它能够更简单的实现局有弹性伸缩能力的原生对象存储服务。

MinIO在传统对象存储用例(例如辅助存储,灾难恢复和归档)方面表现出色。同时,它在机器学习、大数据、私有云、混合云等方面的存储技术上也独树一帜。当然,也不排除数据分析、高性能应用负载、原生云的支持。

在中国:阿里巴巴、腾讯、百度、中国联通、华为、中国移动等等9000多家企业也都在使用MinIO产品

安装 Minio

使用docker安装

拉取镜像

docker pull minio/minio

启动

docker run -p 9000:9000 -p 9001:9001 -d --name minio -v /opt/docker/minio/data:/data -v /opt/docker/minio/config:/root/.minio -e "MINIO_ROOT_USER=minio" -e "MINIO_ROOT_PASSWORD=minio@123456" minio/minio server /data --console-address ":9000" --address ":9001"

使用9000端口 登录控制台

创建存储桶

设置桶权限

创建 Java 客户端

依赖

org.springframework.boot

spring-boot-starter-web

org.springframework.boot

spring-boot-starter-test

test

org.junit.vintage

junit-vintage-engine

org.springframework.boot

spring-boot-configuration-processor

true

org.projectlombok

lombok

true

io.minio

minio

8.2.1

cn.hutool

hutool-all

5.1.2

net.coobird

thumbnailator

0.4.8

org.apache.commons

commons-lang3

3.12.0

com.github.davidcarboni

encrypted-

1.0.0

配置文件

spring:

application:

name: minio-demo

servlet:

multipart:

max-file-size: 20MB

max-request-size: 200MB

server:

port: 8088

minio:

endpoint: http://你的ip:9001

accessKey: minio

secretKey: minio@123456

nginxHost: http://你的域名

配置文件配置类

package com.sqm.minio_demo.config;

import lombok.Data;

import org.springframework.boot.context.properties.ConfigurationProperties;

import org.springframework.stereotype.Component;

@ConfigurationProperties(prefix = "minio")

@Component

@Data

public class MinioProperties {

/**

* 连接地址

*/

private String endpoint;

/**

* 用户名

*/

private String accessKey;

/**

* 密码

*/

private String secretKey;

/**

* 域名

*/

private String nginxHost;

}

创建 minio 客户端

package com.sqm.minio_demo.config;

import io.minio.MinioClient;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.context.properties.EnableConfigurationProperties;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

@Configuration

@EnableConfigurationProperties(MinioProperties.class)

public class MinioConfig {

@Autowired

private MinioProperties minioProperties;

@Bean

public MinioClient minioClient(){

return MinioClient.builder()

.endpoint(minioProperties.getEndpoint())

.credentials(minioProperties.getAccessKey(),minioProperties.getSecretKey())

.build();

}

}

文件地址返回路径实体类

package com.sqm.minio_demo.entity;

import lombok.AllArgsConstructor;

import lombok.Data;

import lombok.NoArgsConstructor;

@Data

@NoArgsConstructor

@AllArgsConstructor

public class UploadResponse {

private String minIoUrl;

private String nginxUrl;

}

上传文件工具类

package com.sqm.minio_demo.util;

import cn.hutool.core.date.DateUtil;

import com.sqm.minio_demo.config.MinioProperties;

import com.sqm.minio_demo.entity.UploadResponse;

import io.minio.*;

import io.minio.errors.*;

import io.minio.messages.Bucket;

import lombok.extern.slf4j.Slf4j;

import net.coobird.thumbnailator.Thumbnails;

import org.apache.commons.fileupload.FileItem;

import org.apache.commons.fileupload.FileItemFactory;

import org.apache.commons.fileupload.disk.DiskFileItemFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Component;

import org.springframework.web.multipart.MultipartFile;

import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.io.File;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.security.InvalidKeyException;

import java.security.NoSuchAlgorithmException;

import java.util.List;

import java.util.Optional;

import java.util.Random;

@Component

@Slf4j

public class MinioUtil {

@Autowired

private MinioProperties minioProperties;

@Autowired

private MinioClient minioClient;

private final Long maxSize = (long) (1024 * 1024);

/**

* 创建bucket

*/

public void createBucket(String bucketName) throws Exception {

if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {

minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());

}

}

http:// /**

* 上传文件

*/

public UploadResponse uploadFile(MultipartFile file, String bucketName) throws Exception {

//判断文件是否为空

if (null == file || 0 == file.getSize()) {

return null;

}

//判断存储桶是否存在 不存在则创建

createBucket(bucketName);

//文件名

String originalFilename = file.getOriginalFilename();

//新的文件名 = 时间戳_随机数.后缀名

assert originalFilename != null;

long now = System.currentTimeMillis() / 1000;

String fileName = DateUtil.format(DateUtil.date(),"yyyyMMdd")+"_"+ now + "_" + new Random().nextInt(1000) +

originalFilename.substring(originalFilename.lastIndexOf("."));

//开始上传

log.info("file压缩前大小:{}",file.getSize());

if (file.getSize() > maxSize) {

FileItemFactory fileItemFactory = new DiskFileItemFactory();

FileItem fileItem = fileItemFactory.createItem(fileName, "text/plain", true, fileName);

OutputStream outputStream = fileItem.getOutputStream();

Thumbnails.of(file.getInputStream()).scale(1f).outputFormat(originalFilename.substring(originalFilename.lastIndexOf(".")+1)).outputQuality(0.25f).toOutputStream(outputStream);

file = new CommonsMultipartFile(fileItem);

}

log.info("file压缩后大小:{}",file.getSize());

minioClient.putObject(

PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(

file.getInputStream(), file.getSize(), -1)

.contentType(file.getContentType())

.build());

String url = minioProperties.getEndpoint() + "/" + bucketName + "/" + fileName;

String urlHost = minioProperties.getNginxHost() + "/" + bucketName + "/" + fileName;

return new UploadResponse(url, urlHost);

}

/**

* 获取全部bucket

*

* @return

*/

public List getAllBuckets() throws Exception {

return minioClient.listBuckets();

}

/**

* 根据bucketName获取信息

*

* @param bucketName bucket名称

*/

public Optional getBucket(String bucketName) throws IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InvalidResponseException, InternalException, ErrorResponseException, ServerException, XmlParserException, ServerException {

return minioClient.listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();

}

/**

* 根据bucketName删除信息

*

* @param bucketName bucket名称

*/

public void removeBucket(String bucketName) throws Exception {

minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());

}

/**

* 获取⽂件外链

*

* @param bucketName bucket名称

* @param objectName ⽂件名称

* @param expires 过期时间 <=7

* @return url

*/

public String getObjectURL(String bucketName, String objectName, Integer expires) throws Exception {

return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(objectName).expiry(expires).build());

}

/**

* 获取⽂件

*

* @param bucketName bucket名称

* @param objectName ⽂件名称

* @return ⼆进制流

*/

public InputStream getObject(String bucketName, String objectName) throws Exception {

return minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());

}

/**

* 上传⽂件

*

* @param bucketName bucket名称

* @param objectName ⽂件名称

* @param stream ⽂件流

* @throws Exception https://docs.minio.io/cn/java-minioClient-api-reference.html#putObject

*/

public void putObject(String bucketName, String objectName, InputStream stream) throws

Exception {

minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(stream, stream.available(), -1).contentType(objectName.substring(objectName.lastIndexOfhttp://("."))).build());

}

/**

* 上传⽂件

*

* @param bucketName bucket名称

* @param objectName ⽂件名称

* @param stream ⽂件流

* @param size ⼤⼩

* @param contextType 类型

* @throws Exception https://docs.minio.io/cn/java-minioClient-api-reference.html#putObject

*/

public void putObject(String bucketName, String objectName, InputStream stream, long

size, String contextType) throws Exception {

minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(stream, size, -1).contentType(contextType).build());

}

/**

* 获取⽂件信息

*

* @param bucketName bucket名称

* @param objectName ⽂件名称

* @throws Exception https://docs.minio.io/cn/java-minioClient-api-reference.html#statObject

*/

public StatObjectResponse getObjectInfo(String bucketName, String objectName) throws Exception {

return minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());

}

/**

* 删除⽂件

*

* @param bucketName bucket名称

* @param objectName ⽂件名称

* @throws Exception https://docs.minio.io/cn/java-minioClient-apireference.html#removeObject

*/

public void removeObject(String bucketName, String objectName) throws Exception {

minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build());

}

/***

* 上传视频

* @param file

* @param bucketName

* @return

* @throws Exception

*/

public UploadResponse uploadVideo(MultipartFile file, String bucketName) throws Exception {

//判断文件是否为空

if (null == file || 0 == file.getSize()) {

return null;

}

//判断存储桶是否存在 不存在则创建

createBucket(bucketName);

//文件名

String originalFilename = file.getOriginalFilename();

//新的文件名 = 时间戳_随机数.后缀名

assert originalFilename != null;

long now = System.currentTimeMillis() / 1000;

String fileName = DateUtil.format(DateUtil.date(),"yyyyMMdd")+"_"+ now + "_" + new Random().nextInt(1000) +

originalFilename.substring(originalFilename.lastIndexOf("."));

//开始上传

log.info("file大小:{}",file.getSize());

minioClient.putObject(

PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(

file.getInputStream(), file.getSize(), -1)

.contentType("video/mp4")

.build());

String url = minioProperties.getEndpoint() + "/" + bucketName + "/" + fileName;

String urlHost = minioProperties.getNginxHost() + "/" + bucketName + "/" + fileName;

return new UploadResponse(url, urlHost);

}

}

测试上传文件 Controller

package com.sqm.minio_demo.controller;

import com.sqm.minio_demo.entity.ResultData;

import com.sqm.minio_demo.entity.UploadResponse;

import com.sqm.minio_demo.util.MinioUtil;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.PostMapping;

import org.springframework.web.bind.annotation.RequestParam;

import org.springframework.web.bind.annotation.RestController;

import org.springframework.web.multipart.MultipartFile;

@RestController

@Slf4j

public class TestController {

@Autowired

private MinioUtil minioUtil;

/**

* @author: xx

* @date: 2022/5/25 15:32

* @description: 上传文件

*/

@PostMapping("/upload")

public ResultData minioUpload(@RequestParam(value = "file") MultipartFile file){

UploadResponse response = null;

try {

response = minioUtil.uploadFile(file, "bucket01");

} catch (Exception e) {

log.error("上传失败",e);

}

return ResultData.ok(response);

}

/**

* @author: xx

* @date: 2022/5/25 15:32

* @description: 上传视频

*/

@PostMapping("/uploadVideo")

public ResultData uploadVideo(@RequestParam(value = "file") MultipartFile file){

UploadResponse response = null;

try {

response = minioUtil.uploadVideo(file, "video-test");

} catch (Exception e) {

log.error("上传失败",e);

}

return ResultData.ok(response);

}

}

测试上传

控制台也可以看到上传的视频

总结


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:springboot+vue完成编辑页面发送接口请求功能
下一篇:手撸一个Spring Boot Starter并上传到Maven中央仓库
相关文章

 发表评论

暂时没有评论,来抢沙发吧~