当前位置: 代码网 > it编程>编程语言>Java > SpringBoot整合Minio实现图片上传功能

SpringBoot整合Minio实现图片上传功能

2024年09月07日 Java 我要评论
minio服务器minio服务器主要功能:保存文件【可以图片、ppt、xsl】1、minio简介minio 是个基于 golang 编写的开源对象存储套件,虽然轻量,却拥有着不错的性能。官网地址:mi

minio服务器

minio服务器主要功能:保存文件【可以图片、ppt、xsl】

1、minio简介

minio 是个基于 golang 编写的开源对象存储套件,虽然轻量,却拥有着不错的性能。

  • 官网地址:minio | high performance, kubernetes native object storage

  • 中文官网地址:http://www.minio.org.cn
    中文文档对应的是上个版本,新版本中有些内容已发生了变化,所以最好是看英文文档。

  • 何为对象存储?
    对象存储服务( object storage service,oss )是一种海量、安全、低成本、高可靠的云存储服务,适合存放任意类型的文件。容量和处理能力弹性扩展,多种存储类型供选择,全面优化存储成本。

对于中小型企业,如果不选择存储上云,那么 minio 是个不错的选择,麻雀虽小,五脏俱全。

2、安装minio

a、下载安装

windows 版下载地址:windows-amd64 版按惯例,我们将下载的 minio.exe 放在 c:\programfiles\minio 下,因此,minio_home 就是 c:\programfiles\minio

b、安装minio

1、下载 minio

安装wget:
	yum -y install wget   #由于需要用到wget命令,所以要先安装wget

创建minio目录:
    mkdir -p /usr/local/minio
    mkdir -p /usr/local/minio/bin
    mkdir -p /usr/local/minio/data
    
进入/usr/local/minio/bin执行如下命令:
	wget https://dl.minio.org.cn/server/minio/release/linux-amd64/minio
	
赋予它可执行权限: 进入到/usr/local/minio/bin中执行如下命令
	chmod +x minio

在usr/local下创建minio文件夹,并在minio文件里面创建bin和data目录,把下载好的minio文件拷贝到bin目录里面

2、将 minio 添加成 linux 的服务

cat > /etc/systemd/system/minio.service << eof
[unit]
description=minio
wants=network-online.target
after=network-online.target
assertfileisexecutable=/usr/local/minio/bin/minio

[service]
workingdirectory=/usr/local/minio/
permissionsstartonly=true
execstart=/usr/local/minio/bin/minio server /usr/local/minio/data
execreload=/bin/kill -s hup $mainpid
execstop=/bin/kill -s quit $mainpid
privatetmp=true

[install]
wantedby=multi-user.target
eof

这样就可以使用 systemctl 启停 minio

systemctl start minio   # 启动
systemctl stop minio    # 停止
systemctl enable minio  #设置自动开启
systemctl status minio # 查看服务运行状态

c、启动运行

输入用户名/密码 minioadmin/minioadmin 可以进入 web 管理系统:

d、创建桶

刚打开的时候,是没有bucket桶,可以手动或者通过java代码来创建一个桶。

创建的桶默认的权限时private私有的,外部不能访问,你可以修改桶的属性,点击manage,找到access policy,修改权限为public即可。

e、上传文件到桶

f、关停 minio

通过命令行启动 mioio 后,命令行窗口就被占用了。关闭命令行窗口即关闭 mioio ,也可以使用 ctrl + c 关闭

3、springboot整合minio

添加minio整合所需的依赖

com.squareup.okhttp3
okhttp
4.8.1


io.minio
minio
8.3.9

设置minio服务器信息

#minio配置
minio:
endpoint: http://127.0.0.1:9000
accesskey: minioadmin
secretkey: minioadmin

创建minion配置类

/**
* minio配置类
*/
@configuration
@data
@configurationproperties(prefix = “minio”)
public class minioconfig {
private string endpoint;
private string accesskey;
private string secretkey;
    /**
     * 创建minioclient对象
     * @return
     * @throws exception
     */
    @bean
    public minioclient minioclient() throws exception {
        return minioclient.builder().endpoint(endpoint)
                .credentials(accesskey, secretkey).build();
    }
}

测试整合结果

4、案例:用户头像上传

文件上传是日常项目中非常常规且常用的一个功能。主要的功能就是将客户端的文件保存到服务器,以便于资源的“浏览”。怎么实现文件上传呢?springmvc中提供了对应的文件上传解析器,按照给定要求,在springmvc的环境下,我们可以很方便的实现上传功能。

文件上传注意事项

  • form 表单的 enctype 取值必须是:multipart/form-data(默认值是:application/x-www-form-urlencoded)

  • method 属性取值必须是 post

  • 提供一个文件选择域,html5原生html中,利用

不过,元素file标签,外观单一,企业级应用中更多的会选择使用外观更加丰富的一些“组件”,比如在element-ui的el-upload组件

el-upload上传组件常用属性

<el-upload
           class="avatar-uploader" action="#"
           :show-file-list="false"
           :before-upload="beforeavatarupload"
           :http-request="douploadimage">
    <img v-if="imageurl" :src="imageurl" class="avatar">
    <i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>

文件上传组件常用属性

  1. action:设置文件上传控制器url地址,属于同步请求提交方式。必备属性
  2. http-request:设置实现上传请求发送的自定义函数名,若要实现自定义上传方式,必须使用http-requeset
  3. :before-upload:处理图片上传过程的钩子,该属性处理图片上传之前的功能。其值设置一个函数,参考上述案例代码:可以判断上传文件的格式和大小

axios.post提交上传请求

因为文件上传的格式必须是:multipart/formdata格式,所以axios.post处理文件上传时,参数较以前的使用,略有变化,具体代码参考如下:

doupload(file){//file 获取用户选择封面图片
    console.log("file",file.file);
    //将用户选择的图片内容封装为formdata类型,才能交给控制器处理
    let formdata=new formdata();
    formdata.append("face",file.file);
    axios.post("/user/do-upload",formdata,{contenttype:'multipart/form-data'})
        .then(resp=>{
        if(resp.data.status===200){
            alert("文件上传成功"+resp.data.msg);
        }else{
            alert("文件上传失败");
        }
    });

代码解读

formdata是javascript提供的一个对象类型,作用封装multipart/form-data格式数据。
formdata对象的append()方法,可以以key:value格式存入数据,控制器在后台以key获取对应的值

contenttype:'multipart/form-data'设置axios.post提交数据格式。
因为axios.post默认提交格式是jsonstring,此处需要手动显式设置数据提交格式:contenttype:'multipart/form-data'

controller控制器后端处理上传请求

springmvc处理文件上传请求时,因为请求体提交数据的格式不再是传统的jsonstring或querystring格式,所以,控制器在处理上传请求前,需要先配置文件上传解析器。具体流程如下所示:

pom.xml导入文件解析器依赖

commons-fileupload commons-fileupload 1.4 commons-io commons-io 2.10.0

pplication.yml配置文件上传解析器

spring:
servlet:
multipart:
max-file-size: 30mb #单个文件的最大上限
max-request-size: 60mb #单个请求的文件总大小上限

controller处理上传请求

@postmapping(“/do-upload”)
public responseresult douploadimage(
@requestparam(value = “aa”,required = true,defaultvalue = “”) multipartfile image
) {
log.info(“用户提交的图书:{}”,image);
//保存文件到minio服务器即可
string bucketname=“woniu-mall”;
//1-1 创建桶
minioutil.createbucket(bucketname);
//1-2 上传文件
string oldname = image.getoriginalfilename();
//文件名称
string firstname = uuid.randomuuid().tostring().replace(“-”, “”);
//文件后缀名
string lastname = oldname.substring(oldname.lastindexof(“.”));
//新的文件名称
string filename=“goods/”+firstname+ lastname;
minioutil.putobject(bucketname,image,filename,image.getcontenttype());
//1-3 获取外链
string objecturl = minioutil.getobjecturl(bucketname, filename);
return new responseresult(200,“上传成功!”,objecturl);
}

处理上传后的响应结果

minio操作工具类

基于springmvc整合minio时,我们在minioconfig中注入过minioclient对象,而minioclient对象就是操作minio服务器的核心对象,该对象提供了在minio服务器上创建桶、上传文件,分享外链给用户使用的功能。为了便于日常的开发使用,我们将这些功能封装成minioutil工具类,开发人员结合开发需求,调用对应方法完成需求即可。工具类的具体代码如下所示:

@slf4j //日志管理工具
@component
public class minioutil {
    @autowired
    private minioclient minioclient;

    /**
     * 创建桶
     * @param bucketname 桶名
     */
    public void createbucket(string bucketname) {
        bucketexistsargs bucketexistsargs = bucketexistsargs.builder().bucket(bucketname).build();
        makebucketargs makebucketargs = makebucketargs.builder().bucket(bucketname).build();

        try {
            if (minioclient.bucketexists(bucketexistsargs)) {
                return;
            }
            minioclient.makebucket(makebucketargs);
        } catch (exception e) {
            //跟sout作用一样,在控制台输出程序执行信息
            log.error("创建桶失败:", e.getmessage());
            throw new runtimeexception(e);
        }
    }

    /**
     * 通过 multipartfile ,上传文件
     *
     * @param bucketname 存储桶
     * @param file       文件
     * @param objectname 对象名(文件名)存入桶时,文件新命名:唯一不重复
     * @param contenttype   文件类型 文件上传时格式
     */
    public objectwriteresponse putobject(string bucketname, multipartfile file, string objectname, string contenttype) {
        try {
            //调用创建桶方法
            createbucket(bucketname);
            //获取文件输入流
            inputstream inputstream = file.getinputstream();
            putobjectargs args = putobjectargs.builder()
                    .bucket(bucketname)
                    .object(objectname)
                    .contenttype(contenttype)
                    .stream(inputstream, inputstream.available(), -1)
                    .build();
            return minioclient.putobject(args);
        } catch (errorresponseexception | insufficientdataexception | internalexception | invalidkeyexception |
                invalidresponseexception | ioexception | nosuchalgorithmexception |
                serverexception | xmlparserexception e) {
            throw new runtimeexception(e);
        }
    }

    /**
     * 获取⽂件外链
     *
     * @param bucketname bucket名称
     * @param objectname ⽂件名称
     * @param expires    过期时间 <=7
     * @param timeunit 有效期时间单位
     */
    public string getobjecturl(string bucketname, string objectname, integer expires, timeunit timeunit) {
        getpresignedobjecturlargs args = getpresignedobjecturlargs.builder()
                .method(method.get)
                .bucket(bucketname)
                .object(objectname)
                .expiry(expires,timeunit)// 单位:默认是,秒
                .build();
        try {
            string url=minioclient.getpresignedobjecturl(args);
            return getimgurl(url);
        } catch (errorresponseexception | insufficientdataexception | internalexception |
                invalidresponseexception | invalidkeyexception | nosuchalgorithmexception |
                ioexception | xmlparserexception | serverexception e) {
            throw new runtimeexception(e);
        }
    }

    /**
     * 获取⽂件外链
     *
     * @param bucketname bucket名称
     * @param objectname ⽂件名称
     */
    public string getobjecturl(string bucketname, string objectname) {
        getpresignedobjecturlargs args = getpresignedobjecturlargs.builder()
                .method(method.get)
                .bucket(bucketname)
                .object(objectname)// 单位:默认是,秒
                .build();
        try {
            string url=minioclient.getpresignedobjecturl(args);
            return getimgurl(url);
        } catch (errorresponseexception | insufficientdataexception | internalexception |
                invalidresponseexception | invalidkeyexception | nosuchalgorithmexception |
                ioexception | xmlparserexception | serverexception e) {
            throw new runtimeexception(e);
        }
    }

    /**
     * 处理图片上传后外链地址
     * 只获得url端口号以后的内容
     * @param urlstr
     * @return
     */
    private string getimgurl(string urlstr){
        if(urlstr.isempty()){
            return "";
        }

        pattern pattern = pattern.compile("\\?"); //通过正则找字符串中的?
        matcher matcher = pattern.matcher(urlstr); //正则表达式比对器
        if (matcher.find()){
            int seartindex = matcher.end();  //获得?开始的位置
            if(seartindex!=-1){
                urlstr=urlstr.substring(0,seartindex-1);
            }
        }

        pattern pattern1 = pattern.compile(":\\d{1,5}"); //通过正则找字符串中的端口
        matcher matcher1 = pattern1.matcher(urlstr); //正则表达式比对器
        if (matcher1.find()){
            int endindex = matcher1.end();  //获得正则表达式规则结束字符串的位置
            if(endindex!=-1){
                return  urlstr.substring(endindex);
            }
        }
        return "";
    }
}

5、常见问题

商品列表:表格图片无法正常显示问题

用户头像显示问题:element组件中el-table默认循环时,没有给每一行指定key,用于标识数据渲染的位置,所以在使用el-avatar显示图片时,会出现图片url地址正确的情况下,图片无法正常显示问题,

解决方案有以下两种:

修改商品信息时:设置图片回显

在商品信息管理时,我们可能会对商品的封面照片进行修改。那么当我们点击“修改”按钮进入到商品修改页面时,一般情况,需要默认显示商品“旧”图片的信息。el-upload组件如何设置默认显示的图片呢?在修改页面初始化数据时,给el-upload组件的imageurl赋值即可完成

以上就是springboot整合minio实现图片上传功能的详细内容,更多关于springboot minio图片上传的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com