当前位置:   article > 正文

spring boot 整合 minio存储 【使用篇】

spring boot 整合 minio存储 【使用篇】

导入依赖

  1. <!--minio-->
  2. <dependency>
  3. <groupId>io.minio</groupId>
  4. <artifactId>minio</artifactId>
  5. <version>8.0.3</version>
  6. </dependency>

yml配置(默认配置)

max-file-size: 200MB 设置文件最大上传大小为200MB,超过则返回错误信息并拒绝文件上传

max-request-size: 100MB 这个配置项指定了整个请求的最大大小限制,包括所有文件和表单数据的大小。如果请求大小超过这个限制,将会拒绝请求并返回错误。

enabled:true 这个配置项指定了文件上传功能是否启用,设置为true表示启用文件上传功能,设置为false表示禁用文件上传功能。当禁用文件上传功能时,任何文件上传请求都将被拒绝。

minion的配置和oss很像,都是这几个需要注入的值

  1. spring:
  2. # 配置文件上传大小限制
  3. servlet:
  4. multipart:
  5. max-file-size: 200MB
  6. max-request-size: 200MB
  7. enabled: true
  8. minio:
  9. endpoint: http://127.0.0.1:9000
  10. accessKey: minioadmin
  11. secretKey: minioadmin
  12. bucketName: bucket-qhj

该图和上面minio配置对应

补充:由于每次启动minio.exe要进入对应目录,很麻烦,所以可以写个批处理文件.bat

  1. @echo off:这是批处理文件的第一行,表示关闭命令回显,即不在命令执行前显示命令本身。

  2. echo.:显示一个空行,这样可以让输出信息更加清晰。

  3. echo [信息] 运行MinIO文服务器。:输出提示信息,告诉用户即将运行MinIO文服务器。

  4. title minio:设置窗口标题为 "minio"。

  5. D:  代表进入D盘

  6. cd D:\Program Files\minio 代表进入你minio.exe存放的根目录

    minio.exe server D:\MineFile\zuoye\xm\minioFile --console-address ":9999" 在D:\MineFile\zuoye\xm\minioFile文件夹执行,并且增加额外端口’9999‘

  1. @echo off
  2. echo.
  3. echo [信息] 运行MinIO文服务器。
  4. echo.
  5. title minio
  6. D:
  7. cd D:\Program Files\minio
  8. minio.exe server D:\MineFile\zuoye\xm\minioFile --console-address ":9999"
  9. pause

配置类

注入客户端配置放入bean

@Data注解:

        自动生成java类的标准方法,getter,setter,toString,equals,hashCode方法等

@Component

        这个注解标识 MinIoClientConfig 类作为一个组件(bean)交给 Spring 容器管理,这样其他地方就可以通过依赖注入来使用该类。

value注解

        装配yml配置文件中的值

@Bean注解

        把minioClient方法注入容器交给 Spring 容器管理

  1. @Data
  2. @Component
  3. public class MinIoClientConfig {
  4. @Value("${minio.endpoint}")
  5. private String endpoint;
  6. @Value("${minio.accessKey}")
  7. private String accessKey;
  8. @Value("${minio.secretKey}")
  9. private String secretKey;
  10. /**
  11. * 注入minio 客户端
  12. * @return
  13. */
  14. @Bean
  15. public MinioClient minioClient(){
  16. return MinioClient.builder()
  17. .endpoint(endpoint)
  18. .credentials(accessKey, secretKey)
  19. .build();
  20. }
  21. }

实体类

用于工具类的调用暂存

  1. @Data
  2. public class ObjectItem {
  3. private String objectName;
  4. private Long size;
  5. }

工具类

根据实体类

  1. /**
  2. * @description: minio工具类
  3. * @version:3.0
  4. */
  5. @Component
  6. public class MinioUtilS {
  7. @Autowired
  8. private MinioClient minioClient;
  9. @Value("${minio.bucketName}")
  10. private String bucketName;
  11. /**
  12. * description: 判断bucket是否存在,不存在则创建
  13. *
  14. * @return: void
  15. */
  16. public void existBucket(String name) {
  17. try {
  18. boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(name).build());
  19. if (!exists) {
  20. minioClient.makeBucket(MakeBucketArgs.builder().bucket(name).build());
  21. }
  22. } catch (Exception e) {
  23. e.printStackTrace();
  24. }
  25. }
  26. /**
  27. * 创建存储bucket
  28. * @param bucketName 存储bucket名称
  29. * @return Boolean
  30. */
  31. public Boolean makeBucket(String bucketName) {
  32. try {
  33. minioClient.makeBucket(MakeBucketArgs.builder()
  34. .bucket(bucketName)
  35. .build());
  36. } catch (Exception e) {
  37. e.printStackTrace();
  38. return false;
  39. }
  40. return true;
  41. }
  42. /**
  43. * 删除存储bucket
  44. * @param bucketName 存储bucket名称
  45. * @return Boolean
  46. */
  47. public Boolean removeBucket(String bucketName) {
  48. try {
  49. minioClient.removeBucket(RemoveBucketArgs.builder()
  50. .bucket(bucketName)
  51. .build());
  52. } catch (Exception e) {
  53. e.printStackTrace();
  54. return false;
  55. }
  56. return true;
  57. }
  58. /**
  59. * description: 上传文件
  60. *
  61. * @param multipartFile
  62. * @return: java.lang.String
  63. */
  64. public List<String> upload(MultipartFile[] multipartFile) {
  65. List<String> names = new ArrayList<>(multipartFile.length);
  66. for (MultipartFile file : multipartFile) {
  67. String fileName = file.getOriginalFilename();
  68. String[] split = fileName.split("\\.");
  69. if (split.length > 1) {
  70. fileName = split[0] + "_" + System.currentTimeMillis() + "." + split[1];
  71. } else {
  72. fileName = fileName + System.currentTimeMillis();
  73. }
  74. InputStream in = null;
  75. try {
  76. in = file.getInputStream();
  77. minioClient.putObject(PutObjectArgs.builder()
  78. .bucket(bucketName)
  79. .object(fileName)
  80. .stream(in, in.available(), -1)
  81. .contentType(file.getContentType())
  82. .build()
  83. );
  84. } catch (Exception e) {
  85. e.printStackTrace();
  86. } finally {
  87. if (in != null) {
  88. try {
  89. in.close();
  90. } catch (IOException e) {
  91. e.printStackTrace();
  92. }
  93. }
  94. }
  95. names.add(fileName);
  96. }
  97. return names;
  98. }
  99. /**
  100. * description: 下载文件
  101. *
  102. * @param fileName
  103. * @return: org.springframework.http.ResponseEntity<byte [ ]>
  104. */
  105. public ResponseEntity<byte[]> download(String fileName) {
  106. ResponseEntity<byte[]> responseEntity = null;
  107. InputStream in = null;
  108. ByteArrayOutputStream out = null;
  109. try {
  110. in = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(fileName).build());
  111. out = new ByteArrayOutputStream();
  112. IOUtils.copy(in, out);
  113. //封装返回值
  114. byte[] bytes = out.toByteArray();
  115. HttpHeaders headers = new HttpHeaders();
  116. try {
  117. headers.add("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
  118. } catch (UnsupportedEncodingException e) {
  119. e.printStackTrace();
  120. }
  121. headers.setContentLength(bytes.length);
  122. headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
  123. headers.setAccessControlExposeHeaders(Arrays.asList("*"));
  124. responseEntity = new ResponseEntity<byte[]>(bytes, headers, HttpStatus.OK);
  125. } catch (Exception e) {
  126. e.printStackTrace();
  127. } finally {
  128. try {
  129. if (in != null) {
  130. try {
  131. in.close();
  132. } catch (IOException e) {
  133. e.printStackTrace();
  134. }
  135. }
  136. if (out != null) {
  137. out.close();
  138. }
  139. } catch (IOException e) {
  140. e.printStackTrace();
  141. }
  142. }
  143. return responseEntity;
  144. }
  145. /**
  146. * 查看文件对象
  147. * @param bucketName 存储bucket名称
  148. * @return 存储bucket内文件对象信息
  149. */
  150. public List<ObjectItem> listObjects(String bucketName) {
  151. Iterable<Result<Item>> results = minioClient.listObjects(
  152. ListObjectsArgs.builder().bucket(bucketName).build());
  153. List<ObjectItem> objectItems = new ArrayList<>();
  154. try {
  155. for (Result<Item> result : results) {
  156. Item item = result.get();
  157. ObjectItem objectItem = new ObjectItem();
  158. objectItem.setObjectName(item.objectName());
  159. objectItem.setSize(item.size());
  160. objectItems.add(objectItem);
  161. }
  162. } catch (Exception e) {
  163. e.printStackTrace();
  164. return null;
  165. }
  166. return objectItems;
  167. }
  168. /**
  169. * 批量删除文件对象
  170. * @param bucketName 存储bucket名称
  171. * @param objects 对象名称集合
  172. */
  173. public Iterable<Result<DeleteError>> removeObjects(String bucketName, List<String> objects) {
  174. List<DeleteObject> dos = objects.stream().map(e -> new DeleteObject(e)).collect(Collectors.toList());
  175. Iterable<Result<DeleteError>> results = minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(dos).build());
  176. return results;
  177. }
  178. }

控制器类

返回可访问的url

@RestController:

         这个注解表示该类是一个 RESTful 服务的控制器,用于处理 HTTP 请求并返回 JSON 格式的响应。

@Slf4j:

        这是 lombok 提供的注解,用于自动生成日志 Logger 对象,可以通过 log 对象进行日志输出。

  1. @RestController
  2. @Slf4j
  3. @RequestMapping("/fileSave")
  4. public class MinioController {
  5. @Autowired
  6. private MinIoUtil minIoUtil;
  7. @Autowired
  8. private MinioUtilS minioUtilS;
  9. @Value("${minio.endpoint}")
  10. private String address;
  11. @Value("${minio.bucketName}")
  12. private String bucketName;
  13. @RequestMapping("/fileInMinio")
  14. public R uploadInMinio(MultipartFile file) {
  15. List<String> upload = minioUtils.upload(new MultipartFile[]{file});
  16. String url = address + "/" + bucketName + "/" + upload.get(0);
  17. return R.ok().put("filePath", url);
  18. }
  19. }

上传后获取链接为

访问报错

解决方式

来到minio控制台

打开你正在使用的bucket

修改访问权限为public就行

重新访问链接,应该就能查看

前端代码

通过父组件导入子组件,注册子组件,引用子组件弹出

父组件调用方法

  1. // 文件导入
  2. importExcel () {
  3. this.uploadFileVisible = true
  4. this.$nextTick(() => {
  5. this.$refs.uploadFile.init()
  6. })
  7. }

 子组件vue页面

包含三种上传方式的切换

  1. <template>
  2. <el-dialog
  3. title="维修处理"
  4. :close-on-click-modal="true"
  5. :visible.sync="visible"
  6. >
  7. <el-select
  8. size="small"
  9. v-model="uploadMethodValue"
  10. placeholder="请选择上传方式"
  11. clearable=""
  12. filterable
  13. >
  14. <el-option
  15. v-for="d in uploadMethod"
  16. :key="d.value"
  17. :label="d.name"
  18. :value="d.value"
  19. ></el-option>
  20. </el-select>
  21. <el-upload
  22. class="upload-demo"
  23. ref="upload"
  24. drag
  25. action="#"
  26. :on-change="handleChangeSelect"
  27. :on-exceed="handleExceed"
  28. :file-list="fileList"
  29. :limit="1"
  30. multiple
  31. :auto-upload="false"
  32. >
  33. <i class="el-icon-upload"></i>
  34. <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
  35. <div
  36. class="el-upload__tip"
  37. slot="tip"
  38. >只能上传jpg/png文件,且不超过500kb</div>
  39. <div
  40. class="el-upload__tip"
  41. slot="tip"
  42. >访问路径:{{ filePath }}</div>
  43. </el-upload>
  44. </el-dialog>
  45. </template>
  46. <script>
  47. export default {
  48. data () {
  49. return {
  50. // 对话框显示状态
  51. visible: false,
  52. uploadMethod: [
  53. { name: '本地存储', value: '1' },
  54. { name: 'oss存储', value: '2' },
  55. { name: 'miniio', value: '3' }
  56. ],
  57. // 选中的上传方式
  58. uploadMethodValue: '',
  59. // 表单数据
  60. dataForm: {
  61. },
  62. filePath: '',
  63. fileList: []
  64. }
  65. },
  66. methods: {
  67. // 初始化方法
  68. init () {
  69. this.visible = true
  70. this.filePath = ''
  71. },
  72. // 文件超出个数提示
  73. handleExceed (files, fileList) {
  74. this.$message.warning(`当前限制选择 1 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`)
  75. },
  76. handleChangeSelect (file) {
  77. if (this.uploadMethodValue === '1') {
  78. // 本地存储
  79. this.handleChange(file, '/fileSave/file')
  80. } else if (this.uploadMethodValue === '2') {
  81. // oss存储
  82. this.handleChange(file, '/fileSave/fileInOSS')
  83. } else if (this.uploadMethodValue === '3') {
  84. // miniio
  85. this.handleChange(file, '/fileSave/fileInMinio')
  86. }
  87. },
  88. handleChange (file, urlSelect) {
  89. let formData = new FormData()
  90. formData.append('file', file.raw) // 传文件
  91. this.$http({
  92. url: this.$http.adornUrl(urlSelect),
  93. method: 'post',
  94. data: formData,
  95. headers: {
  96. 'Content-Type': 'multipart/form-data'
  97. }
  98. }).then(({ data }) => {
  99. if (data && data.code === 0) {
  100. this.filePath = data.filePath
  101. this.$message({
  102. message: '操作成功',
  103. type: 'success',
  104. duration: 1500
  105. })
  106. } else {
  107. this.$message.error(data.msg)
  108. }
  109. this.$refs.upload.clearFiles() // 清除文件
  110. })
  111. }
  112. }
  113. }
  114. </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异常。该方法在实际项目开发中使用较少。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/185287
推荐阅读
相关标签
  

闽ICP备14008679号