当前位置: 代码网 > it编程>编程语言>Java > SpringBoot集成阿里云OSS、华为云OBS、七牛云、又拍云等上传案例【附白嫖方案】【附源码】

SpringBoot集成阿里云OSS、华为云OBS、七牛云、又拍云等上传案例【附白嫖方案】【附源码】

2024年08月01日 Java 我要评论
SpringBoot集成阿里云OSS、华为云OBS、七牛云、又拍云等上传案例,包括个人图床白嫖方案,包含程序的全部源码。

1. 项目背景

唉!本文写起来都是泪点。不是刻意写的本文,主要是对日常用到的文件上传做了一个汇总总结,同时希望可以给用到的小伙伴带来一点帮助吧。

  • 上传本地,这个就不水了,基本做技术的都用到过吧;

  • 阿里云oss,阿里云是业界巨鳄了吧,用到的人肯定不少吧,不过博主好久不用了,简单记录下;

  • 华为云obs,工作需要,也简单记录下吧;

  • 七牛云,个人网站最开始使用的图床,目的是为了白嫖10g文件存储。后来网站了升级了https域名,七牛云免费只支持http,https域名加速是收费的。https域名的网站在谷歌上请求图片时会强制升级为https。

  • 又拍云,个人网站目前在用的图床,加入了又拍云联盟,网站底部挂链接,算是推广合作模式吧(对我这种不介意的来说就是白嫖)。速度还行,可以去我的网站看一下:笑小枫

还有腾讯云等等云,暂没用过,就先不整理了,使用都很简单,sdk文档很全,也很简单。

2. 上传思路

分为两点来说。本文的精华也都在这里了,统一思想。

2.1 前端调用上传文件

前端上传的话,应该是我们常用的吧,通过@requestparam(value = "file") multipartfile file接收,然后转为inputstream or byte[] or file,然后调用上传就可以了,核心也就在这,很简单的,尤其上传到云服务器,装载好配置后,直接调用sdk接口即可。

2.2 通过url地址上传网络文件

通过url上传应该很少用到吧,使用场景呢,例如爬取文章的时候,把网络图片上传到自己的图床;图片库根据url地址迁移。

说到这,突然想起了一个问题,大家写文章的时候,图片上传到图床后在文章内是怎么保存的呢?是全路径还是怎么保存的?如果加速域名换了,或者换图床地址了,需要怎么迁移。希望有经验的大佬可以留言指导!

3. 上传到本地

这个比较简单啦,贴下核心代码吧

  • 在yml配置下上传路径
file:
  local:
    maxfilesize: 10485760
    imagefilepath: d:/test/image/
    docfilepath: d:/test/file/
  • 创建配置类,读取配置文件的参数
package com.maple.upload.properties;


import lombok.data;
import org.springframework.beans.factory.annotation.value;
import org.springframework.context.annotation.configuration;

/**
 * 上传本地配置
 *
 * @author 笑小枫
 * @date 2022/7/22
 * @see <a href="https://www.xiaoxiaofeng.com">https://www.xiaoxiaofeng.com</a>
 */
@data
@configuration
public class localfileproperties {

    // ---------------本地文件配置 start------------------
    /**
     * 图片存储路径
     */
    @value("${file.local.imagefilepath}")
    private string imagefilepath;

    /**
     * 文档存储路径
     */
    @value("${file.local.docfilepath}")
    private string docfilepath;

    /**
     * 文件限制大小
     */
    @value("${file.local.maxfilesize}")
    private long maxfilesize;
    // --------------本地文件配置 end-------------------

}
  • 创建上传下载工具类
package com.maple.upload.util;

import com.maple.upload.properties.localfileproperties;
import lombok.allargsconstructor;
import lombok.extern.slf4j.slf4j;
import org.apache.commons.lang3.stringutils;
import org.springframework.stereotype.component;
import org.springframework.web.multipart.multipartfile;

import javax.servlet.servletoutputstream;
import javax.servlet.http.httpservletresponse;
import java.io.file;
import java.io.fileinputstream;
import java.io.ioexception;
import java.io.unsupportedencodingexception;
import java.net.urldecoder;
import java.nio.charset.standardcharsets;
import java.nio.file.files;
import java.text.simpledateformat;
import java.util.*;

/**
 * @author 笑小枫
 * @date 2024/1/10
 * @see <a href="https://www.xiaoxiaofeng.com">https://www.xiaoxiaofeng.com</a>
 */
@slf4j
@component
@allargsconstructor
public class localfileutil {
    private final localfileproperties fileproperties;


    private static final list<string> file_type_list_image = arrays.aslist(
            "image/png",
            "image/jpg",
            "image/jpeg",
            "image/bmp");

    /**
     * 上传图片
     */
    public string uploadimage(multipartfile file) {
        // 检查图片类型
        string contenttype = file.getcontenttype();
        if (!file_type_list_image.contains(contenttype)) {
            throw new runtimeexception("上传失败,不允许的文件类型");
        }
        int size = (int) file.getsize();
        if (size > fileproperties.getmaxfilesize()) {
            throw new runtimeexception("文件过大");
        }
        string filename = file.getoriginalfilename();
        //获取文件后缀
        string aftername = stringutils.substringafterlast(filename, ".");
        //获取文件前缀
        string prefname = stringutils.substringbeforelast(filename, ".");
        //获取一个时间毫秒值作为文件名
        filename = new simpledateformat("yyyymmddhhmmss").format(new date()) + "_" + prefname + "." + aftername;
        file filepath = new file(fileproperties.getimagefilepath(), filename);

        //判断文件是否已经存在
        if (filepath.exists()) {
            throw new runtimeexception("文件已经存在");
        }
        //判断文件父目录是否存在
        if (!filepath.getparentfile().exists()) {
            filepath.getparentfile().mkdirs();
        }
        try {
            file.transferto(filepath);
        } catch (ioexception e) {
            log.error("图片上传失败", e);
            throw new runtimeexception("图片上传失败");
        }
        return filename;
    }

    /**
     * 批量上传文件
     */
    public list<map<string, object>> uploadfiles(multipartfile[] files) {
        int size = 0;
        for (multipartfile file : files) {
            size = (int) file.getsize() + size;
        }
        if (size > fileproperties.getmaxfilesize()) {
            throw new runtimeexception("文件过大");
        }
        list<map<string, object>> fileinfolist = new arraylist<>();
        for (int i = 0; i < files.length; i++) {
            map<string, object> map = new hashmap<>();
            string filename = files[i].getoriginalfilename();
            //获取文件后缀
            string aftername = stringutils.substringafterlast(filename, ".");
            //获取文件前缀
            string prefname = stringutils.substringbeforelast(filename, ".");

            string fileservicename = new simpledateformat("yyyymmddhhmmss")
                    .format(new date()) + i + "_" + prefname + "." + aftername;
            file filepath = new file(fileproperties.getdocfilepath(), fileservicename);
            // 判断文件父目录是否存在
            if (!filepath.getparentfile().exists()) {
                filepath.getparentfile().mkdirs();
            }
            try {
                files[i].transferto(filepath);
            } catch (ioexception e) {
                log.error("文件上传失败", e);
                throw new runtimeexception("文件上传失败");
            }
            map.put("filename", filename);
            map.put("filepath", filepath);
            map.put("fileservicename", fileservicename);
            fileinfolist.add(map);
        }
        return fileinfolist;
    }

    /**
     * 批量删除文件
     *
     * @param filenamearr 服务端保存的文件的名数组
     */
    public void deletefile(string[] filenamearr) {
        for (string filename : filenamearr) {
            string filepath = fileproperties.getdocfilepath() + filename;
            file file = new file(filepath);
            if (file.exists()) {
                try {
                    files.delete(file.topath());
                } catch (ioexception e) {
                    e.printstacktrace();
                    log.warn("文件删除失败", e);
                }
            } else {
                log.warn("文件: {} 删除失败,该文件不存在", filename);
            }
        }
    }

    /**
     * 下载文件
     */
    public void downloadfile(httpservletresponse response, string filename) throws unsupportedencodingexception {
        string encodefilename = urldecoder.decode(filename, "utf-8");
        file file = new file(fileproperties.getdocfilepath() + encodefilename);
        // 下载文件
        if (!file.exists()) {
            throw new runtimeexception("文件不存在!");
        }
        try (fileinputstream inputstream = new fileinputstream(file);
             servletoutputstream outputstream = response.getoutputstream()) {
            response.reset();
            //设置响应类型	pdf文件为"application/pdf",word文件为:"application/msword", excel文件为:"application/vnd.ms-excel"。
            response.setcontenttype("application/octet-stream;charset=utf-8");
            //设置响应的文件名称,并转换成中文编码
            string aftername = stringutils.substringafterlast(filename, "_");
            //保存的文件名,必须和页面编码一致,否则乱码
            aftername = response.encodeurl(new string(aftername.getbytes(), standardcharsets.iso_8859_1.displayname()));
            response.setheader("content-type", "application-download");
            //attachment作为附件下载;inline客户端机器有安装匹配程序,则直接打开;注意改变配置,清除缓存,否则可能不能看到效果
            response.addheader("content-disposition", "attachment;filename=" + aftername);
            response.addheader("filename", aftername);
            //将文件读入响应流
            int length = 1024;
            byte[] buf = new byte[1024];
            int readlength = inputstream.read(buf, 0, length);
            while (readlength != -1) {
                outputstream.write(buf, 0, readlength);
                readlength = inputstream.read(buf, 0, length);
            }
            outputstream.flush();
        } catch (exception e) {
            e.printstacktrace();
        }
    }
}

访问图片的话,可以通过重写webmvcconfigureraddresourcehandlers方法来实现。

通过请求/local/images/**将链接虚拟映射到我们配置的localfileproperties.getimagefilepath()下,文件访问同理。

详细代码如下

package com.maple.upload.config;

import com.maple.upload.properties.localfileproperties;
import lombok.allargsconstructor;
import org.springframework.context.annotation.configuration;
import org.springframework.web.servlet.config.annotation.resourcehandlerregistry;
import org.springframework.web.servlet.config.annotation.webmvcconfigurer;

/**
 * @author 笑小枫 <https://www.xiaoxiaofeng.com/>
 * @date 2024/1/10
 */
@configuration
@allargsconstructor
public class localfileconfig implements webmvcconfigurer {

    private final localfileproperties localfileproperties;

    @override
    public void addresourcehandlers(resourcehandlerregistry registry) {
        // 重写方法
        // 修改tomcat 虚拟映射
        // 定义图片存放路径
        registry.addresourcehandler("/local/images/**").
                addresourcelocations("file:" + localfileproperties.getimagefilepath());
        //定义文档存放路径
        registry.addresourcehandler("/local/doc/**").
                addresourcelocations("file:" + localfileproperties.getdocfilepath());
    }
}
  • controller调用代码
package com.maple.upload.controller;

import com.maple.upload.util.localfileutil;
import lombok.allargsconstructor;
import lombok.extern.slf4j.slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.multipartfile;

import javax.servlet.http.httpservletresponse;
import java.util.list;
import java.util.map;

/**
 * 文件相关操作接口
 *
 * @author 笑小枫
 * @date 2024/1/10
 * @see <a href="https://www.xiaoxiaofeng.com">https://www.xiaoxiaofeng.com</a>
 */
@slf4j
@restcontroller
@allargsconstructor
@requestmapping("/local")
public class localfilecontroller {

    private final localfileutil fileutil;

    /**
     * 图片上传
     */
    @postmapping("/uploadimage")
    public string uploadimage(@requestparam(value = "file") multipartfile file) {
        if (file.isempty()) {
            throw new runtimeexception("图片内容为空,上传失败!");
        }
        return fileutil.uploadimage(file);
    }

    /**
     * 文件批量上传
     */
    @postmapping("/uploadfiles")
    public list<map<string, object>> uploadfiles(@requestparam(value = "file") multipartfile[] files) {
        return fileutil.uploadfiles(files);
    }

    /**
     * 批量删除文件
     */
    @postmapping("/deletefiles")
    public void deletefiles(@requestparam(value = "files") string[] files) {
        fileutil.deletefile(files);
    }

    /**
     * 文件下载功能
     */
    @getmapping(value = "/download/{filename:.*}")
    public void download(@pathvariable("filename") string filename, httpservletresponse response) {
        try {
            fileutil.downloadfile(response, filename);
        } catch (exception e) {
            log.error("文件下载失败", e);
        }
    }
}

调用上传图片的接口,可以看到图片已经上传成功。

image-20240116102717345

通过请求/local/images/**将链接虚拟映射我们图片上。

image-20240116103037587

批量上传,删除等操作就不一一演示截图了,代码已贴,因为是先写的demo,后写的文章,获取代码片贴的有遗漏,如有遗漏,可以去文章底部查看源码地址。

4. 上传阿里云oss

更多公共云下oss region和endpoint对照,参考上面链接

image-20240116103832968

  • 引入oss sdk依赖
        <!-- 阿里云oss -->
        <dependency>
            <groupid>com.aliyun.oss</groupid>
            <artifactid>aliyun-sdk-oss</artifactid>
            <version>3.8.1</version>
        </dependency>
  • 配置上传配置信息
file:
  oss:
    bucketname: maplebucket
    accesskeyid: your ak
    secretaccesskey: your sk
    endpoint: oss-cn-shanghai.aliyuncs.com
    showurl: cdn地址-file.xiaoxiaofeng.com
  • 创建配置类,读取配置文件的参数
/*
 * copyright (c) 2018-2999 上海合齐软件科技科技有限公司 all rights reserved.
 *
 *
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */

package com.maple.upload.properties;


import lombok.data;
import org.springframework.beans.factory.annotation.value;
import org.springframework.context.annotation.configuration;

/**
 * 阿里云oss配置
 *
 * @author 笑小枫 <https://www.xiaoxiaofeng.com/>
 * @date 2024/1/10
 */
@data
@configuration
public class aliossproperties {

    @value("${file.oss.bucketname}")
    private string bucketname;

    @value("${file.oss.accesskeyid}")
    private string accesskeyid;

    @value("${file.oss.secretaccesskey}")
    private string secretaccesskey;

    @value("${file.oss.endpoint}")
    private string endpoint;

    @value("${file.oss.showurl}")
    private string showurl;
}

  • 上传工具类
package com.maple.upload.util;

import com.aliyun.oss.oss;
import com.aliyun.oss.ossclientbuilder;
import com.aliyun.oss.model.putobjectresult;
import com.maple.upload.properties.aliossproperties;
import lombok.allargsconstructor;
import lombok.extern.slf4j.slf4j;
import org.apache.commons.lang3.stringutils;
import org.springframework.stereotype.component;
import org.springframework.web.multipart.multipartfile;

import java.io.inputstream;

/**
 * 阿里云oss 对象存储工具类
 * 阿里云oss官方sdk使用文档:https://help.aliyun.com/zh/oss/developer-reference/java
 * 阿里云oss操作指南:https://help.aliyun.com/zh/oss/user-guide
 * 
 * @author 笑小枫 <https://www.xiaoxiaofeng.com/>
 * @date 2024/1/15
 */
@slf4j
@component
@allargsconstructor
public class aliossutil {

    private final aliossproperties aliossproperties;

    public string uploadfile(multipartfile file) {
        string filename = file.getoriginalfilename();
        if (stringutils.isblank(filename)) {
            throw new runtimeexception("获取文件信息失败");
        }
        // 组建上传的文件名称,命名规则可自定义更改
        string objectkey = filecommonutil.setfilepath("xiaoxiaofeng") + filecommonutil.setfilename("xxf", filename.substring(filename.lastindexof(".")));

        //构造一个oss对象的配置类
        oss ossclient = new ossclientbuilder().build(aliossproperties.getendpoint(), aliossproperties.getaccesskeyid(), aliossproperties.getsecretaccesskey());
        try (inputstream inputstream = file.getinputstream()) {
            log.info(string.format("阿里云oss上传开始,原文件名:%s,上传后的文件名:%s", filename, objectkey));
            putobjectresult result = ossclient.putobject(aliossproperties.getbucketname(), objectkey, inputstream);
            log.info(string.format("阿里云oss上传结束,文件名:%s,返回结果:%s", objectkey, result.tostring()));
            return aliossproperties.getshowurl() + objectkey;
        } catch (exception e) {
            log.error("调用阿里云oss失败", e);
            throw new runtimeexception("调用阿里云oss失败");
        }
    }
}

因为篇幅问题,controller就不贴了。暂时没有阿里云oss的资源了,这里就不做测试,小伙伴在使用过程中如有问题,麻烦留言告诉我下!

5. 上传华为云obs

  • 引入sdk依赖
        <!-- 华为云obs -->
        <dependency>
            <groupid>com.huaweicloud</groupid>
            <artifactid>esdk-obs-java-bundle</artifactid>
            <version>3.21.8</version>
        </dependency>
  • 配置上传配置信息
file:
  obs:
    bucketname: maplebucket
    accesskey: your ak
    secretkey: your sk
    endpoint: obs.cn-east-2.myhuaweicloud.com
    showurl: cdn地址-file.xiaoxiaofeng.com
  • 创建配置类,读取配置文件的参数
package com.maple.upload.properties;

import lombok.data;
import org.springframework.beans.factory.annotation.value;
import org.springframework.context.annotation.configuration;

/**
 * 华为云上传配置
 *
 * @author 笑小枫 <https://www.xiaoxiaofeng.com/>
 * @date 2024/1/10
 */
@data
@configuration
public class hwyobsproperties {

    @value("${file.obs.bucketname}")
    private string bucketname;

    @value("${file.obs.accesskey}")
    private string accesskey;

    @value("${file.obs.secretkey}")
    private string secretkey;

    @value("${file.obs.endpoint}")
    private string endpoint;

    @value("${file.obs.showurl}")
    private string showurl;
}
  • 上传工具类
package com.maple.upload.util;

import com.alibaba.fastjson.json;
import com.maple.upload.bean.hwyobsmodel;
import com.maple.upload.properties.hwyobsproperties;
import com.obs.services.obsclient;
import com.obs.services.exception.obsexception;
import com.obs.services.model.postsignaturerequest;
import com.obs.services.model.postsignatureresponse;
import com.obs.services.model.putobjectresult;
import lombok.allargsconstructor;
import lombok.extern.slf4j.slf4j;
import org.apache.commons.lang3.stringutils;
import org.springframework.stereotype.component;
import org.springframework.web.multipart.multipartfile;

import java.io.ioexception;
import java.io.inputstream;

/**
 * 华为云obs 对象存储工具类
 * 华为云obs官方sdk使用文档:https://support.huaweicloud.com/sdk-java-devg-obs/obs_21_0101.html
 * 华为云obs操作指南:https://support.huaweicloud.com/ugobs-obs/obs_41_0002.html
 * 华为云各服务应用区域和各服务的终端节点:https://developer.huaweicloud.com/endpoint?obs
 *
 * @author 笑小枫
 * @date 2022/7/22
 * @see <a href="https://www.xiaoxiaofeng.com">https://www.xiaoxiaofeng.com</a>
 */
@slf4j
@component
@allargsconstructor
public class hwyobsutil {

    private final hwyobsproperties fileproperties;

    /**
     * 上传华为云obs文件存储
     *
     * @param file 文件
     * @return 文件访问路径, 如果配置cdn,这里直接返回cdn+文件名(objectkey)
     */
    public string uploadfiletoobs(multipartfile file) {
        string filename = file.getoriginalfilename();
        if (stringutils.isblank(filename)) {
            throw new runtimeexception("获取文件信息失败");
        }
        // 文件类型
        string filetype = filename.substring(file.getoriginalfilename().lastindexof("."));
        // 组建上传的文件名称,命名规则可自定义更改
        string objectkey = filecommonutil.setfilepath("") + filecommonutil.setfilename(null, filetype);
        putobjectresult putobjectresult;
        try (inputstream inputstream = file.getinputstream();
             obsclient obsclient = new obsclient(fileproperties.getaccesskey(), fileproperties.getsecretkey(), fileproperties.getendpoint())) {
            log.info(string.format("华为云obs上传开始,原文件名:%s,上传后的文件名:%s", filename, objectkey));
            putobjectresult = obsclient.putobject(fileproperties.getbucketname(), objectkey, inputstream);
            log.info(string.format("华为云obs上传结束,文件名:%s,返回结果:%s", objectkey, json.tojsonstring(putobjectresult)));
        } catch (obsexception | ioexception e) {
            log.error("华为云obs上传文件失败", e);
            throw new runtimeexception("华为云obs上传文件失败,请重试");
        }
        if (putobjectresult.getstatuscode() == 200) {
            return putobjectresult.getobjecturl();
        } else {
            throw new runtimeexception("华为云obs上传文件失败,请重试");
        }
    }

    /**
     * 获取华为云上传token,将token返回给前端,然后由前端上传,这样文件不占服务器端带宽
     *
     * @param filename 文件名称
     * @return
     */
    public hwyobsmodel getobsconfig(string filename) {
        if (stringutils.isblank(filename)) {
            throw new runtimeexception("the filename cannot be empty.");
        }
        string obstoken;
        string objectkey = null;
        try (obsclient obsclient = new obsclient(fileproperties.getaccesskey(), fileproperties.getsecretkey(), fileproperties.getendpoint())) {

            string filetype = filename.substring(filename.lastindexof("."));
            // 组建上传的文件名称,命名规则可自定义更改
            objectkey = filecommonutil.setfilepath("") + filecommonutil.setfilename("", filetype);

            postsignaturerequest request = new postsignaturerequest();
            // 设置表单上传请求有效期,单位:秒
            request.setexpires(3600);
            request.setbucketname(fileproperties.getbucketname());
            if (stringutils.isnotblank(objectkey)) {
                request.setobjectkey(objectkey);
            }
            postsignatureresponse response = obsclient.createpostsignature(request);
            obstoken = response.gettoken();
        } catch (obsexception | ioexception e) {
            log.error("华为云obs上传文件失败", e);
            throw new runtimeexception("华为云obs上传文件失败,请重试");
        }
        hwyobsmodel obsmodel = new hwyobsmodel();
        obsmodel.setbucketname(fileproperties.getbucketname());
        obsmodel.setendpoint(fileproperties.getendpoint());
        obsmodel.settoken(obstoken);
        obsmodel.setobjectkey(objectkey);
        obsmodel.setshowurl(fileproperties.getshowurl());
        return obsmodel;
    }
}

篇幅问题,不贴controller和测试截图了,完整代码参考文章底部源码吧,思想明白了,别的都大差不差。

6. 上传七牛云

  • 引入sdk依赖
        <!-- 七牛云 -->
        <dependency>
            <groupid>com.qiniu</groupid>
            <artifactid>qiniu-java-sdk</artifactid>
            <version>7.2.29</version>
        </dependency>
  • 配置上传配置信息
file:
  qiniuyun:
    bucket: maplebucket
    accesskey: your ak
    secretkey: your sk
    regionid: z1
    showurl: cdn地址-file.xiaoxiaofeng.com
  • 创建配置类,读取配置文件的参数
package com.maple.upload.properties;

import lombok.data;
import org.springframework.beans.factory.annotation.value;
import org.springframework.context.annotation.configuration;

/**
 * 七牛云配置
 *
 * @author 笑小枫 <https://www.xiaoxiaofeng.com/>
 * @date 2024/1/10
 */
@data
@configuration
public class qiniuproperties {

    @value("${file.qiniuyun.accesskey}")
    private string accesskey;

    @value("${file.qiniuyun.secretkey}")
    private string secretkey;

    @value("${file.qiniuyun.bucket}")
    private string bucket;
    
    @value("${file.qiniuyun.regionid}")
    private string regionid;

    @value("${file.qiniuyun.showurl}")
    private string showurl;
}
  • 上传工具类,注意有一个区域转换,如后续有新增,qiniuconfig这里需要调整一下
package com.maple.upload.util;

import com.maple.upload.properties.qiniuproperties;
import com.qiniu.http.response;
import com.qiniu.storage.configuration;
import com.qiniu.storage.region;
import com.qiniu.storage.uploadmanager;
import com.qiniu.util.auth;
import lombok.allargsconstructor;
import lombok.extern.slf4j.slf4j;
import org.apache.commons.lang3.stringutils;
import org.springframework.stereotype.component;
import org.springframework.web.multipart.multipartfile;

import java.io.inputstream;
import java.util.objects;

/**
 * 
 * 七牛云 对象存储工具类
 * 七牛云官方sdk:https://developer.qiniu.com/kodo/1239/java
 * 七牛云存储区域表链接:https://developer.qiniu.com/kodo/1671/region-endpoint-fq
 * 
 * @author 笑小枫 <https://www.xiaoxiaofeng.com/>
 * @date 2022/3/24
 */
@slf4j
@component
@allargsconstructor
public class qiniuyunutil {

    private final qiniuproperties qiniuproperties;

    public string uploadfile(multipartfile file) {
        string filename = file.getoriginalfilename();
        if (stringutils.isblank(filename)) {
            throw new runtimeexception("获取文件信息失败");
        }
        // 组建上传的文件名称,命名规则可自定义更改
        string objectkey = filecommonutil.setfilepath("xiaoxiaofeng") + filecommonutil.setfilename("xxf", filename.substring(filename.lastindexof(".")));

        //构造一个带指定 region 对象的配置类
        configuration cfg = qiniuconfig(qiniuproperties.getregionid());
        //...其他参数参考类注释
        uploadmanager uploadmanager = new uploadmanager(cfg);
        try (inputstream inputstream = file.getinputstream()) {
            auth auth = auth.create(qiniuproperties.getaccesskey(), qiniuproperties.getsecretkey());
            string uptoken = auth.uploadtoken(qiniuproperties.getbucket());
            log.info(string.format("七牛云上传开始,原文件名:%s,上传后的文件名:%s", filename, objectkey));
            response response = uploadmanager.put(inputstream, objectkey, uptoken, null, null);
            log.info(string.format("七牛云上传结束,文件名:%s,返回结果:%s", objectkey, response.tostring()));
            return qiniuproperties.getshowurl() + objectkey;
        } catch (exception e) {
            log.error("调用七牛云失败", e);
            throw new runtimeexception("调用七牛云失败");
        }
    }

    private static configuration qiniuconfig(string zone) {
        region region = null;
        if (objects.equals(zone, "z1")) {
            region = region.huabei();
        } else if (objects.equals(zone, "z0")) {
            region = region.huadong();
        } else if (objects.equals(zone, "z2")) {
            region = region.huanan();
        } else if (objects.equals(zone, "na0")) {
            region = region.beimei();
        } else if (objects.equals(zone, "as0")) {
            region = region.xinjiapo();
        }
        return new configuration(region);
    }
}

篇幅问题,不贴controller和测试截图了,完整代码参考文章底部源码吧,思想明白了,别的都大差不差。

7. 上传又拍云

  • 引入sdk依赖
        <!-- 又拍云oss -->
        <dependency>
            <groupid>com.upyun</groupid>
            <artifactid>java-sdk</artifactid>
            <version>4.2.3</version>
        </dependency>
  • 配置上传配置信息
file:
  upy:
    bucketname: maplebucket
    username: 操作用户名称
    password: 操作用户密码
    showurl: cdn地址-file.xiaoxiaofeng.com
  • 创建配置类,读取配置文件的参数
package com.maple.upload.properties;

import lombok.data;
import org.springframework.beans.factory.annotation.value;
import org.springframework.context.annotation.configuration;

/**
 * 又拍云上传配置
 *
 * @author 笑小枫 <https://www.xiaoxiaofeng.com/>
 * @date 2024/1/10
 */
@data
@configuration
public class upyossproperties {

    @value("${file.upy.bucketname}")
    private string bucketname;

    @value("${file.upy.username}")
    private string username;

    @value("${file.upy.password}")
    private string password;

    /**
     * 加速域名
     */
    @value("${file.upy.showurl}")
    private string showurl;
}
  • 上传工具类
package com.maple.upload.util;

import com.maple.upload.properties.upyossproperties;
import com.upyun.restmanager;
import com.upyun.upexception;
import lombok.allargsconstructor;
import lombok.extern.slf4j.slf4j;
import okhttp3.response;
import org.apache.commons.io.ioutils;
import org.apache.commons.lang3.stringutils;
import org.springframework.stereotype.component;
import org.springframework.web.multipart.multipartfile;

import java.io.ioexception;
import java.io.inputstream;
import java.net.uri;

/**
 * 又拍云 对象存储工具类
 * 又拍云客户端配置:https://help.upyun.com/knowledge-base/quick_start/
 * 又拍云官方sdk:https://github.com/upyun/java-sdk
 *
 * @author 笑小枫
 * @date 2022/7/22
 * @see <a href="https://www.xiaoxiaofeng.com">https://www.xiaoxiaofeng.com</a>
 */
@slf4j
@component
@allargsconstructor
public class upyossutil {

    private final upyossproperties fileproperties;

    /**
     * 根据url上传文件到又拍云
     */
    public string uploadupy(string url) {
        // 组建上传的文件名称,命名规则可自定义更改
        string filename = filecommonutil.setfilepath("xiaoxiaofeng") + filecommonutil.setfilename("xxf", url.substring(url.lastindexof(".")));
        restmanager restmanager = new restmanager(fileproperties.getbucketname(), fileproperties.getusername(), fileproperties.getpassword());

        uri u = uri.create(url);
        try (inputstream inputstream = u.tourl().openstream()) {
            byte[] bytes = ioutils.tobytearray(inputstream);
            response response = restmanager.writefile(filename, bytes, null);
            if (response.issuccessful()) {
                return fileproperties.getshowurl() + filename;
            }
        } catch (ioexception | upexception e) {
            log.error("又拍云oss上传文件失败", e);
        }
        throw new runtimeexception("又拍云oss上传文件失败,请重试");
    }

    /**
     * multipartfile上传文件到又拍云
     */
    public string uploadupy(multipartfile file) {
        string filename = file.getoriginalfilename();
        if (stringutils.isblank(filename)) {
            throw new runtimeexception("获取文件信息失败");
        }
        // 组建上传的文件名称,命名规则可自定义更改
        string objectkey = filecommonutil.setfilepath("xiaoxiaofeng") + filecommonutil.setfilename("xxf", filename.substring(filename.lastindexof(".")));
        restmanager restmanager = new restmanager(fileproperties.getbucketname(), fileproperties.getusername(), fileproperties.getpassword());

        try (inputstream inputstream = file.getinputstream()) {
            log.info(string.format("又拍云上传开始,原文件名:%s,上传后的文件名:%s", filename, objectkey));
            response response = restmanager.writefile(objectkey, inputstream, null);
            log.info(string.format("又拍云上传结束,文件名:%s,返回结果:%s", objectkey, response.issuccessful()));
            if (response.issuccessful()) {
                return fileproperties.getshowurl() + objectkey;
            }
        } catch (ioexception | upexception e) {
            log.error("又拍云oss上传文件失败", e);
        }
        throw new runtimeexception("又拍云oss上传文件失败,请重试");
    }
}

篇幅问题,不贴controller和测试截图了,完整代码参考文章底部源码吧,思想明白了,别的都大差不差。

8. 项目源码

本文到此就结束了,如果帮助到你了,帮忙点个赞👍

本文源码:https://github.com/hack-feng/maple-product/tree/main/maple-file-upload

(0)

相关文章:

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

发表评论

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