zi导入依赖
<!--minio-->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.0.3</version>
</dependency>
yml配置(默认配置)
spring:
# 配置文件上传大小限制
servlet:
multipart:
max-file-size: 200MB
max-request-size: 200MB
minio:
endpoint: http://127.0.0.1:9000
accessKey: minioadmin
secretKey: minioadmin
bucketName: bucket-qhj
一一对应
补充:由于每次启动minio.exe要进入对应目录,很麻烦,所以可以写个批处理文件.bat
D: 代表进入D盘
cd D:\Program Files\minio 代表进入你minio.exe存放的根目录
minio.exe server D:\MineFile\zuoye\xm\minioFile --console-address ":9999" 在D:\MineFile\zuoye\xm\minioFile文件夹执行,并且增加额外端口’9999‘
@echo off
echo.
echo [信息] 运行MinIO文服务器。
echo.
title minio
D:
cd D:\Program Files\minio
minio.exe server D:\MineFile\zuoye\xm\minioFile --console-address ":9999"
pause
配置类
注入客户端配置放入bean
使用value注解装配yml配置文件中的值
@Data
@Component
public class MinIoClientConfig {
@Value("${minio.endpoint}")
private String endpoint;
@Value("${minio.accessKey}")
private String accessKey;
@Value("${minio.secretKey}")
private String secretKey;
/**
* 注入minio 客户端
* @return
*/
@Bean
public MinioClient minioClient(){
return MinioClient.builder()
.endpoint(endpoint)
.credentials(accessKey, secretKey)
.build();
}
}
实体类
@Data
public class ObjectItem {
private String objectName;
private Long size;
}
工具类
根据实体类
/**
* @description: minio工具类
* @version:3.0
*/
@Component
public class MinioUtilS {
@Autowired
private MinioClient minioClient;
@Value("${minio.bucketName}")
private String bucketName;
/**
* description: 判断bucket是否存在,不存在则创建
*
* @return: void
*/
public void existBucket(String name) {
try {
boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(name).build());
if (!exists) {
minioClient.makeBucket(MakeBucketArgs.builder().bucket(name).build());
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 创建存储bucket
* @param bucketName 存储bucket名称
* @return Boolean
*/
public Boolean makeBucket(String bucketName) {
try {
minioClient.makeBucket(MakeBucketArgs.builder()
.bucket(bucketName)
.build());
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 删除存储bucket
* @param bucketName 存储bucket名称
* @return Boolean
*/
public Boolean removeBucket(String bucketName) {
try {
minioClient.removeBucket(RemoveBucketArgs.builder()
.bucket(bucketName)
.build());
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* description: 上传文件
*
* @param multipartFile
* @return: java.lang.String
*/
public List<String> upload(MultipartFile[] multipartFile) {
List<String> names = new ArrayList<>(multipartFile.length);
for (MultipartFile file : multipartFile) {
String fileName = file.getOriginalFilename();
String[] split = fileName.split("\\.");
if (split.length > 1) {
fileName = split[0] + "_" + System.currentTimeMillis() + "." + split[1];
} else {
fileName = fileName + System.currentTimeMillis();
}
InputStream in = null;
try {
in = file.getInputStream();
minioClient.putObject(PutObjectArgs.builder()
.bucket(bucketName)
.object(fileName)
.stream(in, in.available(), -1)
.contentType(file.getContentType())
.build()
);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
names.add(fileName);
}
return names;
}
/**
* description: 下载文件
*
* @param fileName
* @return: org.springframework.http.ResponseEntity<byte [ ]>
*/
public ResponseEntity<byte[]> download(String fileName) {
ResponseEntity<byte[]> responseEntity = null;
InputStream in = null;
ByteArrayOutputStream out = null;
try {
in = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(fileName).build());
out = new ByteArrayOutputStream();
IOUtils.copy(in, out);
//封装返回值
byte[] bytes = out.toByteArray();
HttpHeaders headers = new HttpHeaders();
try {
headers.add("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
headers.setContentLength(bytes.length);
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setAccessControlExposeHeaders(Arrays.asList("*"));
responseEntity = new ResponseEntity<byte[]>(bytes, headers, HttpStatus.OK);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return responseEntity;
}
/**
* 查看文件对象
* @param bucketName 存储bucket名称
* @return 存储bucket内文件对象信息
*/
public List<ObjectItem> listObjects(String bucketName) {
Iterable<Result<Item>> results = minioClient.listObjects(
ListObjectsArgs.builder().bucket(bucketName).build());
List<ObjectItem> objectItems = new ArrayList<>();
try {
for (Result<Item> result : results) {
Item item = result.get();
ObjectItem objectItem = new ObjectItem();
objectItem.setObjectName(item.objectName());
objectItem.setSize(item.size());
objectItems.add(objectItem);
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
return objectItems;
}
/**
* 批量删除文件对象
* @param bucketName 存储bucket名称
* @param objects 对象名称集合
*/
public Iterable<Result<DeleteError>> removeObjects(String bucketName, List<String> objects) {
List<DeleteObject> dos = objects.stream().map(e -> new DeleteObject(e)).collect(Collectors.toList());
Iterable<Result<DeleteError>> results = minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(dos).build());
return results;
}
}
控制器类
返回可访问的url
@RestController
@Slf4j
@RequestMapping("/fileSave")
public class MinioController {
@Autowired
private MinIoUtil minIoUtil;
@Autowired
private MinioUtilS minioUtilS;
@Value("${minio.endpoint}")
private String address;
@Value("${minio.bucketName}")
private String bucketName;
@RequestMapping("/fileInMinio")
public R uploadInMinio(MultipartFile file) {
List<String> upload = minioUtils.upload(new MultipartFile[]{file});
String url = address + "/" + bucketName + "/" + upload.get(0);
return R.ok().put("filePath", url);
}
}
上传后获取链接为
访问报错
解决方式
来到minio控制台
打开你正在使用的bucket
修改访问权限为public就行
重新访问链接,应该就能查看
前端代码
通过父组件导入子组件,注册子组件,引用子组件弹出
父组件调用方法
// 文件导入
importExcel () {
this.uploadFileVisible = true
this.$nextTick(() => {
this.$refs.uploadFile.init()
})
}
子组件vue页面
<template>
<el-dialog
title="维修处理"
:close-on-click-modal="true"
:visible.sync="visible"
>
<el-select
size="small"
v-model="uploadMethodValue"
placeholder="请选择上传方式"
clearable=""
filterable
>
<el-option
v-for="d in uploadMethod"
:key="d.value"
:label="d.name"
:value="d.value"
></el-option>
</el-select>
<el-upload
class="upload-demo"
ref="upload"
drag
action="#"
:on-change="handleChangeSelect"
:on-exceed="handleExceed"
:file-list="fileList"
:limit="1"
multiple
:auto-upload="false"
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<div
class="el-upload__tip"
slot="tip"
>只能上传jpg/png文件,且不超过500kb</div>
<div
class="el-upload__tip"
slot="tip"
>访问路径:{{ filePath }}</div>
</el-upload>
</el-dialog>
</template>
<script>
export default {
data () {
return {
// 对话框显示状态
visible: false,
uploadMethod: [
{ name: '本地存储', value: '1' },
{ name: 'oss存储', value: '2' },
{ name: 'miniio', value: '3' }
],
// 选中的上传方式
uploadMethodValue: '',
// 表单数据
dataForm: {
},
filePath: '',
fileList: []
}
},
methods: {
// 初始化方法
init () {
this.visible = true
this.filePath = ''
},
// 文件超出个数提示
handleExceed (files, fileList) {
this.$message.warning(`当前限制选择 1 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`)
},
handleChangeSelect (file) {
if (this.uploadMethodValue === '1') {
// 本地存储
this.handleChange(file, '/fileSave/file')
} else if (this.uploadMethodValue === '2') {
// oss存储
this.handleChange(file, '/fileSave/fileInOSS')
} else if (this.uploadMethodValue === '3') {
// miniio
this.handleChange(file, '/fileSave/fileInMinio')
}
},
handleChange (file, urlSelect) {
let formData = new FormData()
formData.append('file', file.raw) // 传文件
this.$http({
url: this.$http.adornUrl(urlSelect),
method: 'post',
data: formData,
headers: {
'Content-Type': 'multipart/form-data'
}
}).then(({ data }) => {
if (data && data.code === 0) {
this.filePath = data.filePath
this.$message({
message: '操作成功',
type: 'success',
duration: 1500
})
} else {
this.$message.error(data.msg)
}
this.$refs.upload.clearFiles() // 清除文件
})
}
}
}
</script>
拓展学习
MultipartFile
MultipartFile为org.springframework.web.mutipart包下的一个类,也就是说如果想使用MultipartFile这个类就必须引入spring框架,换句话说,如果想在项目中使用MultipartFile这个类,那么项目必须要使用spring框架才可以,否则无法引入这个类。
一般来讲使用MultipartFile这个类主要是来实现以表单的形式进行文件上传功能。
MiltipartFile类注释说明
第一句:一种可以接收使用多种请求方式来进行上传文件的代表形式。也就是说,如果你想用spring框架来实现项目中的文件上传功能,则MultipartFile可能是最合适的选择,而这里提到的多种请求方式则可以通俗理解为以表单的形式提交。
第二句:这个文件内容可以存储到内存中或者存储在磁盘的临时位置上。
第三句:无论发生哪种情况,用户都可以自由地拷贝文件内容到session存储中,或者以一种永久存储的形式进行存储,如果有需要的话。
第四句:这种临时性的存储在请求结束之后将会被清除掉。
类中方法
getName方法
获取的是前后端约定的传入文件的参数的名称,在SpringBoot后台中则是通过@Param("uploadFile") 注解定义的内容。
getOriginalFileName方法
getOriginalFileName方法获取的是文件的完整名称,包括文件名称+文件拓展名。
getContentType方法
getContentType方法获取的是文件的类型,注意是文件的类型,不是文件的拓展名。
getBytes方法
getBytes方法用来将文件转换成一种字节数组的方式进行传输,会抛出IOException异常。
getInputStream方法
getInputStream方法用来将文件转换成输入流的形式来传输文件,会抛出IOException异常。
transferTo方法
transferTo方法用来将接收文件传输到给定目标路径,会抛出IOException、IllegalStateException异常。该方法在实际项目开发中使用较少。