SpringBoot 对接 MinIO 实现文件上传下载删除

前言

MinIO 是一个开源的对象存储服务器,它可以存储大容量非结构化的数据,例如图片、音频、视频、日志文件、备份数据和容器/虚拟机镜像等。

Spring Boot 与 MinIO 的整合可以方便地实现文件的上传和下载等功能

在实际应用中,Spring Boot 对接 MinIO 可以用于以下场景:

  • 文件存储:将文件存储在 MinIO 中,以便在需要时进行访问和下载。
  • 数据备份:将数据备份到 MinIO 中,以便在需要时进行恢复。
  • 容器镜像存储:将 Docker 容器镜像存储在 MinIO 中,以便在需要时进行访问和下载。
  • 静态资源存储:将静态资源(如 CSS、JavaScript 和图像)存储在 MinIO 中,以便在需要时进行访问和下载。

通过 Spring Boot 对接 MinIO,你可以方便地管理和操作文件存储,并且可以根据自己的需求进行扩展和定制化

MinIO 安装

MinIO 安装参考:Linux 部署 MinIO 分布式对象存储 & 配置为 typora 图床

引入依赖

maven 依赖

<dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.5.2</version>
</dependency>

配置

配置文件

在 application.yml 中添加

minio:endpoint: http://192.168.101.3:9001access-key: DHgpKILqY5iNa88LByHx  # minio 的 accessKeysecret-key: Ppa9Nxes7jOkbBD2BTuFhjFcfGjw3lXmXUItKcBV  # minio 的 secretKey

创建配置类

对应配置文件

@Data
@Component
@ConfigurationProperties(prefix = "minio")
public class MinioInfo {private String endpoint;private String accessKey;private String secretKey;
}

配置客户端

配置 minio 操作客户端

@Configuration
@EnableConfigurationProperties(MinioInfo.class)
public class MinioConfig {@Autowiredprivate MinioInfo minioInfo;/*** 获取 minioClient*/@Beanpublic MinioClient minioClient() throws NoSuchAlgorithmException, KeyManagementException {return MinioClient.builder().endpoint(minioInfo.getEndpoint()).credentials(minioInfo.getAccessKey(),minioInfo.getSecretKey()).build();}
}

工具类封装

@Slf4j
@Component
public class MinioUtils {@Autowiredprivate MinioClient minioClient;@Autowiredprivate MinioInfo minioInfo;/*** 上传文件** @param file       文件信息* @param bucketName minio bucket 名称* @return 上传文件路径*/public String uploadFile(MultipartFile file, String bucketName) {if (file == null || file.getSize() == 0) {log.error("minio 上传文件:{}", "上传文件不能为空");return null;}try {// 判断是否存在createBucket(bucketName);// 原文件名String originalFilename = file.getOriginalFilename();minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(originalFilename).stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build());return minioInfo.getEndpoint() + "/" + bucketName + "/" + originalFilename;} catch (Exception e) {log.error("minio 上传失败:{}", e.getMessage());}log.error("minio 上传文件:{}", "上传失败");return null;}/*** 通过字节流上传** @param imageFullPath 图片路径* @param bucketName    minio bucket 名称* @param imageData     图片数据* @return 上传文件路径*/public String uploadImage(String imageFullPath,String bucketName,byte[] imageData) {ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(imageData);try {//判断是否存在createBucket(bucketName);minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(imageFullPath).stream(byteArrayInputStream, byteArrayInputStream.available(), -1).contentType(".jpg").build());return minioInfo.getEndpoint() + "/" + bucketName + "/" + imageFullPath;} catch (Exception e) {log.error("minio 上传失败:{}", e.getMessage());}log.error("minio 上传失败:{}", "上传失败");return null;}/*** 删除文件** @param bucketName minio bucket 名称* @param fileName 文件名* @return*/public Boolean removeFile(String bucketName, String fileName) {try {//判断桶是否存在boolean res = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());if (res) {//删除文件minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(fileName).build());}} catch (Exception e) {log.error("minio 删除文件失败");e.printStackTrace();return false;}return true;}/*** 下载文件** @param fileName 文件名* @param bucketName minio bucket 名称* @param response 请求响应*/public void fileDownload(String fileName,String bucketName,HttpServletResponse response) {InputStream inputStream = null;OutputStream outputStream = null;try {if (StringUtils.isBlank(fileName)) {response.setHeader("Content-type", "text/html;charset=UTF-8");String data = "文件下载失败";OutputStream ps = response.getOutputStream();ps.write(data.getBytes("UTF-8"));return;}outputStream = response.getOutputStream();// 获取文件对象inputStream = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(fileName).build());byte buf[] = new byte[1024];int length = 0;response.reset();response.setHeader("Content-Disposition", "attachment;filename=" +URLEncoder.encode(fileName.substring(fileName.lastIndexOf("/") + 1), "UTF-8"));response.setContentType("application/octet-stream");response.setCharacterEncoding("UTF-8");// 输出文件while ((length = inputStream.read(buf)) > 0) {outputStream.write(buf, 0, length);}System.out.println("下载成功");inputStream.close();} catch (Throwable ex) {response.setHeader("Content-type", "text/html;charset=UTF-8");String data = "文件下载失败";try {OutputStream ps = response.getOutputStream();ps.write(data.getBytes("UTF-8"));} catch (IOException e) {e.printStackTrace();}} finally {try {outputStream.close();if (inputStream != null) {inputStream.close();}} catch (IOException e) {e.printStackTrace();}}}@SneakyThrowspublic void createBucket(String bucketName) {// 不存在就创建if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());}}
}

使用

上传文件

@RestController
@RequestMapping("/minio")
public class TestMinioController {@Resourceprivate MinioUtils minioUtils;/*** 上传文件* @param file 文件* @return 路径*/@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)@ResponseBodypublic BaseResponse<String> uploadByMinio(@RequestParam(name = "file") MultipartFile file) {//返回存储路径String path = minioUtils.uploadFile(file, "minio-img");return ResultUtils.success(path);}
}

请求参数为 file,类型为 file,响应回来的 data 为文件路径

image-20231009150510183

请求成功后,可以在 minio 中查看

image-20231009150620190

下载文件

根据文件名下载文件

/*** 根据文件名下载文件** @param fileName 文件名* @param response 请求响应体*/
@GetMapping("/download")
public void downloadByMinio(@RequestParam(name = "fileName") String fileName,HttpServletResponse response) {try {minioUtils.fileDownload(fileName, "minio-img", response);} catch (Exception e) {e.printStackTrace();}
}

请求参数为 fileName

image-20231009151358994

删除文件

/*** 根据文件名删除文件** @param fileName 文件名* @return 是否成功*/
@PostMapping("/delete")
@ResponseBody
public BaseResponse<String> deleteByMonio(String fileName) {Boolean result = minioUtils.removeFile("minio-img", fileName);if (!result) {return ResultUtils.error(ErrorCode.SYSTEM_ERROR,"删除失败");}return ResultUtils.success("删除成功");
}

image-20231009151511984

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/130564.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

再获深交所认可,Smartbi实力领跑金融BI赛道

“十四五”规划中提到&#xff0c;健全具有高度适应性、竞争力、普惠性的现代金融体系&#xff0c;构建有效支撑实体经济的体制机制。《证券期货业科技发展“十四五”规划》作为指导证券期货业科技发展的纲领性文件&#xff0c; 秉承国家“十四五”规划的数字化发展理念&#x…

flutter开发实战-Universal Links配置及flutter微信分享实现

flutter开发实战-Universal Links配置及flutter微信分享实现 在最近开发中碰到了需要实现微信分享&#xff0c;在iOS端需要配置UniversalLink&#xff0c;在分享使用fluwx插件来实现微信分享功能。 一、配置UniversalLink 1.1、什么是UniversalLink Universal link 是Apple…

在asp.net中,实现类似安卓界面toast的方法(附更多弹窗样式)

目录 一、背景 二、操作方法 2.1修改前 2.2修改后 三、总结 附&#xff1a;参考文章&#xff1a; 一、背景 最近在以前的asp.net网页中&#xff0c;每次点击确定都弹窗&#xff0c;然后还要弹窗点击确认&#xff0c;太麻烦了&#xff0c;这次想升级一下&#xff0c;实现…

ES知识点全面整理

● 我们从很多年前就知道 ES6, 也就是官方发布的 ES2015 ● 从 2015 年开始, 官方觉得大家命名太乱了, 所以决定以年份命名 ● 但是大家还是习惯了叫做 ES6, 不过这不重要 ● 重要的是, ES6 关注的人非常多, 大家也会主动去关注 ● 但是从 2016 年以后, 每年官方都会出现新…

ToBeWritten之车联网安全中常见的TOP 10漏洞

也许每个人出生的时候都以为这世界都是为他一个人而存在的&#xff0c;当他发现自己错的时候&#xff0c;他便开始长大 少走了弯路&#xff0c;也就错过了风景&#xff0c;无论如何&#xff0c;感谢经历 转移发布平台通知&#xff1a;将不再在CSDN博客发布新文章&#xff0c;敬…

用《斗破苍穹》的视角打开C#委托2 委托链 / 泛型委托 / GetInvocationList

委托链 经过不懈地努力&#xff0c;我终于成为了斗师&#xff0c;并成功掌握了两种斗技——八极崩和焰分噬浪尺。于是&#xff0c;我琢磨着&#xff0c;能不能搞一套连招&#xff0c;直接把对方带走。 using System; using System.Collections.Generic; using System.Linq; u…

串联起深度学习的整体,以及其他领域

1、从模型拟合&#xff08;收敛&#xff09;数据关系出发&#xff1a; 2、f从简单的一层和两层连接开始&#xff0c;发展&#xff1b;被表示成 3、如何判断收敛&#xff1a;,即目标函数 4、如何界定任务&#xff1a;&#xff0c;表示什么&#xff1f;表示什么&#xff1f;&a…

【Java 进阶篇】CSS 属性

当你学习CSS时&#xff0c;了解CSS属性是非常重要的&#xff0c;因为这些属性控制了网页上元素的外观和布局。本文将详细介绍一些常见的CSS属性&#xff0c;包括文本属性、盒子模型属性、背景和边框属性、定位属性等。我们还将为每个属性提供示例代码&#xff0c;以便你更好地理…

Xcode 15下,包含个推的项目运行时崩溃的处理办法

升级到Xcode15后&#xff0c;部分包含个推的项目在iOS17以下的系统版本运行时&#xff0c;会出现崩溃&#xff0c;由于崩溃在个推Framework内部&#xff0c;无法定位到具体代码&#xff0c;经过和个推官方沟通&#xff0c;确认问题是项目支持的最低版本问题。 需要将项目的最低…

android app开发环境搭建

Android是流行的移动设备原生应用开发平台&#xff0c;其支持Java语言以及Kotlin语言的开发环境&#xff0c;本文主要描述官方提供的Android studio集成开发环境搭建。 https://developer.android.google.cn/ 如上所示&#xff0c;从官方上下载最新版本的Android studio集成开…

ESP-07S进行TCP 通信测试

一&#xff0c;TCP Server 为 AP 模式&#xff0c;TCP Client 为 Station 模式。 这里电脑pc作为TCP Server&#xff0c;ESP-07S作为TCP Client 。 二&#xff0c;电脑端配置。 1&#xff0c;开启热点。 2&#xff0c;转到“设置”&#xff0c;编辑热点信息。 3&#xff0c;关闭…

华为数通方向HCIP-DataCom H12-831题库(多选题:241-259)

第241题 设备产生的信息可以向多个方向输出信息,为了便于各个方向信息的输出控制,信息中心定义了10条信息通道,使通道之间独立输出,缺省情况下,以下哪些通道对应的输出方向可以接收Trap信息? A、console通道 B、logbuffer通道 C、snmpagent通道 D、trapbuffer通道 答案:…