springboot+minio 文件上传

前期准备

需要先安装minio文件服务器,请参考我上一篇文章

pom.xml 版本

本次使用的是springboot2.7.16 版本,
minio 版本是8.2.2

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.16</version>
        <relativePath/>
    </parent>


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

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.11</version>
        </dependency>

配置minio服务

minio.endpoint=**********
minio.accessKey=******
minio.secretKey=*******
minio.bucketName=shuangningzixun
# 单个文件上传的最大值
spring.servlet.mutipart.max-file-size=200MB
# 整个请求体上传的文件大小
spring.servlet.mutipart.max-request-size=500MB

其中endpoint 为本地安装的minio服务地址,形式为IP+端口
accessKey和secretKey为用户名密码
桶名称则是在minio服务上新增的桶名称。

minio配置类

package com.example.demo.config;

import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MinioConfig {

    /**
     * 访问地址
     */
    @Value("${minio.endpoint}")
    private String endpoint;

    /**
     * accessKey类似于用户ID,用于唯一标识你的账户
     */
    @Value("${minio.accessKey}")
    private String accessKey;

    /**
     * secretKey是你账户的密码
     */
    @Value("${minio.secretKey}")
    private String secretKey;

    /**
     * 默认存储桶
     */
    @Value("${minio.bucketName}")
    private String bucketName;

    @Bean
    public MinioClient minioClient() {
        MinioClient minioClient = MinioClient.builder()
                .endpoint(endpoint)
                .credentials(accessKey, secretKey)
                .build();
        return minioClient;
    }
}

minio配置实体类

package com.example.demo.config;


import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@ConfigurationProperties(prefix="minio")
@Component
@Getter
@Setter
public class Minio {
    private String url;
    private String username;
    private String password;
    private String bucketName;

}

minio下载服务类

package com.example.demo.service;

import com.example.demo.config.Minio;
import io.minio.BucketExistsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

@Component
public class MinioService {

    @Autowired
    private MinioClient minioClient;

    @Autowired
    private Minio minio;

    public String uploadFile(MultipartFile file) throws IOException {
        //判断捅是否存在
        String url=null;
        try {
            boolean bucketExists = minioClient.bucketExists(BucketExistsArgs
                    .builder().bucket(minio.getBucketName()).build());
            if (!bucketExists){
                //如果不存在,就创建捅
                minioClient.makeBucket(MakeBucketArgs.builder().
                        bucket(minio.getBucketName()).build());
            }
            String yyyyMMdd = LocalDateTime.now().
                    format(DateTimeFormatter.ofPattern("yyyy-mm-dd"));
            String uuid = UUID.randomUUID().toString();
            String filename = yyyyMMdd +"/"+file.getOriginalFilename();
            //
            minioClient.putObject(PutObjectArgs.builder().
                    bucket(minio.getBucketName())
                    .object(uuid).stream(file.getInputStream(),file.getSize(),-1)
                    .contentType(file.getContentType()).build());
          url  = minio.getUrl()+"/"+minio.getBucketName()+"/"+filename;
            return url;
        } catch (Exception e) {

        }finally {
            file.getInputStream().close();
        }
        return url;
    }
}

minio 上传文件工具类

package com.example.demo.utils;

import io.minio.GetObjectArgs;
import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.InputStream;

@Component
public class MinioUtils {

    @Autowired
    private MinioClient minioClient;

    public InputStream getObject(String bucketName, String objectName) throws Exception {
        return minioClient.getObject(GetObjectArgs.builder()
                .bucket(bucketName).object(objectName).build());

    }
}

文件控制器

package com.example.demo.controller;

import com.example.demo.common.ApiResult;
import com.example.demo.config.Minio;
import com.example.demo.service.MinioService;
import com.example.demo.utils.MinioUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;

@RestController
@RequestMapping("/file")
@Slf4j
public class FileController {
    @Autowired
    private MinioService minioService;

    @Autowired
    private MinioUtils minioUtils;

    @Autowired
    private Minio minio;

    /**
     * 文件上传接口
     */
    @PostMapping("/upload")
    public ApiResult<Void> upload(@RequestParam("file")MultipartFile multipartFile) throws Exception{
        minioService.uploadFile(multipartFile);
       return null;
    }

    /**
     * 文件下载接口
     */
    @GetMapping("/download")
    public void  download(@RequestParam("fileName")String fileName,
                          HttpServletResponse response) {
        try {
            InputStream fileInputStream = minioUtils.getObject(minio.getBucketName(),fileName);
            response.setHeader("Content-Disposition","attachment;filename="+fileName);
            response.setContentType("application/force-download");
            response.setCharacterEncoding("UTF-8");
            IOUtils.copy(fileInputStream,response.getOutputStream());
        } catch (Exception e) {
           log.info("下载失败",e);
        }
    }
}

postman测试

在这里插入图片描述
可以在minio控制台查询到已经上传的文件。
到此一个简单的文件上传下载服务就算成功了

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

利用AI办公工具类API,大幅提高办公效率

AI办公工具类API是一项革命性的技术&#xff0c;利用人工智能的力量为办公场景提供了许多创新的解决方案。借助AI办公工具类API&#xff0c;用户可以实现自动化的文档处理、语音转文字、图像识别、数据分析等多种功能&#xff0c;大大提高了办公效率和工作质量。此外&#xff0…

Uni-App开发 导入(引入)Vant-Weapp组件;支持vue3/vue2版本和微信小程序

文章目录 目录 文章目录 操作流程 小结 概要安装流程技术细节小结 概要 Vant Weapp官网&#xff1a;Vant Weapp - 轻量、可靠的小程序 UI 组件库 准备工作&#xff0c;需要确保自己的电脑上已安装Hbuilde和node 全程操作的环境都需要这些配合才能运行上&#xff0c;可参考作者…

如何彻底搞懂组合(Composite)设计模式?

当我们在设计系统对象关系时&#xff0c;有时候会碰到这样一种场景&#xff0c;一个对象中包含了另一组对象&#xff0c;两者构成一种”部分-整体”的关联关系。 正如上图中所展示的&#xff0c;当我们面对这样一种对象关系时&#xff0c;通常都需要分别构建单独的访问方式&…

数据挖掘案例-航空公司客户价值分析

文章目录 1. 案例背景2. 分析方法与过程2.1 分析流程步骤2.2 分析过程1. 数据探索分析2. 描述性统计分析3. 分布分析1.客户基本信息分布分析2. 客户乘机信息分布分析3. 客户积分信息分布分析 4. 相关性分析 3. 数据预处理3.1 数据清洗3.2 属性约束3. 3 数据转换 4. 模型构建4. …

【面经】单片机

1、单片机IO口工作方式 输入 模拟输入&#xff08;GPIO_Mode_AIN&#xff09;&#xff1a;关闭施密特触发器&#xff0c;将电压信号传送到片上外设模块&#xff0c;通常用于连接模拟信号源。浮空输入&#xff08;GPIO_Mode_IN_FLOATING&#xff09;&#xff1a;在浮空输入状态…

回收站清空的文件怎么恢复?8个方法公开(2024更新版)

“我太粗心了&#xff0c;刚想恢复部分回收站中误删的重要文件&#xff0c;一不小心把回收站清空了&#xff0c;现在还有什么方法可以恢复它们吗&#xff1f;” 在数字时代&#xff0c;电脑已经成为我们日常生活和工作中不可或缺的工具。然而&#xff0c;随着我们对电脑的依赖加…

etcd 和 MongoDB 的混沌(故障注入)测试方法

最近在对一些自建的数据库 driver/client 基础库的健壮性做混沌&#xff08;故障&#xff09;测试, 去验证了解业务的故障处理机制和恢复时长. 主要涉及到了 MongoDB 和 etcd 这两个基础组件. 本文会介绍下相关的测试方法. MongoDB 中的故障测试 MongoDB 是比较世界上热门的文…

【算法】排序——加更

补充1个排序&#xff1a;希尔排序 思路&#xff1a;首先定义一个gap,从第0个数开始&#xff0c;每隔一个gap取出一个数&#xff0c;将取出来的数进行比较&#xff0c;方法类似插入排序。第二轮从第二个数开始&#xff0c;每隔一个gap取出一个数再进行插入排序。四轮就可以取完…

新手一次过软考高级(系统规划与管理师)秘笈,请收藏!

2024上软考已经圆满结束&#xff0c;距离下半年的考试也只剩下半年不到的时间。需要备考下半年软考高级的小伙伴们可以抓紧开始准备了&#xff0c;毕竟高级科目的难度可是不低的。 今天给大家整理了——系统规划与管理师的备考资料 &#xff0c;都是核心重点&#xff0c;有PDF&…

微博v14.5.1,集成猪手模块2.3.0-276,移除广告和各类推广提示

软件介绍 微博 v14.5.1&#xff0c;内置猪手模块直装版是一款专业优化的微消客户端&#xff0c;该软件融合了咸猪手模块&#xff0c;并提供了用户友好的自定义选项。这些选项包括广告移除、停止推荐内容、消除各类提示消息等功能&#xff0c;旨在提升用户的个性化使用体验。 …

最详细Linux提权总结(建议收藏)

1、内核漏洞脏牛提权 查看内核版本信息 uname -a 具体提权 1、信息收集配合kali提权 uname -a #查看内核版本信息 内核版本为3.2.78&#xff0c;那我们可以搜索该版本漏洞 searchsploit linux 3.2.78 找到几个可以使用的脏牛提权脚本&#xff0c;这里我使用的是40839.c脚…

Facebook广告如何开户以及投放费用?

Facebook作为全球最大的社交媒体平台之一&#xff0c;成为了企业与个人推广品牌、产品或服务的重要渠道。其精准的广告定向功能和庞大的用户基数&#xff0c;为广告主提供了无限的商机。云衔科技为企业提供专业的Facebook上开户和运营服务&#xff0c;助力您高效获客。 一、Fa…

【Spring Cloud】Feign整合服务容错中间件Sentinel

文章目录 引入sentinel依赖配置文件为被容错的接口指定容错类创建容错类修改controller演示扩展为被容错的接口更改容错类创建回退工厂类演示 总结 上一篇文章中我们已经对服务容错中间件 Sentinel 持久化的两种模式进行了全面解析&#xff0c;本文我们将对Feign和Sentinel进行…

学术图表的基本配色方法

不论是商业图表还是专业图表&#xff0c;图表的配色都极其关键。图表配色主要有彩色和黑白两种配色方案。刘万祥老师曾提出&#xff1a; “在我看来&#xff0c;普通图表与专业图表的差别&#xff0c;很大程度就体现在颜色运用上。” 对于科学图表&#xff0c;大部分国内的期…

lua 计算第几周

需求 计算当前赛季的开始和结束日期&#xff0c;2024年1月1日周一是第1周的开始&#xff0c;每两周是一个赛季。 lua代码 没有处理时区问题 local const 24 * 60 * 60 --一整天的时间戳 local server_time 1716595200--todo:修改服务器时间 local date os.date("*t…

利用阅读APP3.0目录展示要查看的内容02

要实现前面提到的功能并不困难&#xff0c;只要导入如下规则即可: 打开APP导入对应规则: 导入后的目录规则界面: 导入后的替换规则界面: 规则文件详细内容: 1. 目录规则&#xff1a; 2. 替换规则 除了直接导入上述文件&#xff0c;也可以自己添加规则。总之&#xff0c;就是利用…

蓝桥杯第十四届国赛B组刷题笔记

A-0子2023&#xff1a; 题目&#xff1a; 小蓝在黑板上连续写下从 11 到 20232023 之间所有的整数&#xff0c;得到了一个数字序列&#xff1a; &#x1d446;12345678910111213...20222023S12345678910111213...20222023。 小蓝想知道 &#x1d446;S 中有多少种子序列恰好等…

夏日将至,给手机装个“液冷”降温可行吗?

夏天出门在外&#xff0c;手机总是更容易发热&#xff0c;尤其是顶着大太阳用手机的时候&#xff0c;更是考验手机的散热能力。如果你也是一个对手机体验有追求的人&#xff0c;比较在意手机的温度&#xff0c;那么可以考虑入手一个微泵液冷手机壳。 【什么是微泵液冷壳&#…

《浪姐》也搞live直播,真成综艺流量密码了?

继《歌手》之后&#xff0c;芒果的另一档综艺《浪姐》也将开启直播。 《乘风2024》官博宣布进行突击加场直播赛&#xff0c;姐姐们将面临全开麦live直播&#xff0c;摇人投票排在前十的姐姐获得live直播抢先权。 这是看《歌手2024》直播赛制火了&#xff0c;也想蹭个热度搞直…

JavaScript 新特性:新增声明命令与解构赋值的强大功能

个人主页&#xff1a;学习前端的小z 个人专栏&#xff1a;JavaScript 精粹 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结&#xff0c;欢迎大家在评论区交流讨论&#xff01; ES5、ES6介绍 文章目录 &#x1f4af;声明命令 let、const&#x1f35f;1 let声明符&a…