SpringBoot整合七牛云OSS对象存储服务实现文件上传与删除

前面不是讲了SpringBoot邮箱服务以及使用Redis存储验证码吗,这里和前两章的关联性不大,但是仍然是我们开发中常用的--整合OSS对象存储服务

这里以七牛云为例,用这个纯属是因为好用(免费)

首先,我们得注册一个七牛云账号,还要申请个空间,不过内陆的好像有一定的限制,我用的海外的

找到密钥管理,创建一个密钥

记住这个密钥,有用,还有你申请的空间信息

我这里绑定了自己的域名

接下来就是和SpringBoot整合了

Maven配置

下面来配置Maven,从官方SDK文档可以看到

下面是我用的

        <!-- https://mvnrepository.com/artifact/com.qiniu/qiniu-java-sdk -->
        <dependency>
            <groupId>com.qiniu</groupId>
            <artifactId>qiniu-java-sdk</artifactId>
            <version>7.2.28</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.5</version>
        </dependency>

yml配置

qiniu:
  accessKey: 【根据自身需求进行配置】
  secretKey: 【根据自身需求进行配置】
  # 对象储存
  bucket: 【根据自身需求进行配置】 # 空间名称
  zone: 【根据自身需求进行配置】 # 存储区域 那个地方的就写缩写就行,具体的我们还要写配置类
  domain: 【根据自身需求进行配置】 # 访问域名 不用加上http(s)://和末尾的/

QiNiuConfig

/**
 * Title
 *
 * @ClassName: qQiniuConfig
 * @Description: 七牛云配置
 * @author: Karos
 * @date: 2022/10/19 8:32
 * @Blog: https://www.wzl1.top/
 */

package com.karos.td.Config.FileCloud;

import com.google.gson.Gson;
import com.qiniu.common.Zone;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.UploadManager;
import com.qiniu.util.Auth;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration("QiNiuConfig")
public class QiNiuConfig {
    @Value("${qiniu.accessKey}")
    private String accessKey;

    @Value("${qiniu.secretKey}")
    private String secretKey;

    @Value("${qiniu.zone}")
    private String zone;

    /**
     * 配置空间的存储区域
     * <p>
     * 注意所有Bean首字母小写后,昵称不能一样
     */
    @Bean
    public com.qiniu.storage.Configuration qiNiuConfig() throws Exception {
        switch (zone) {
            case "huadong":
                return new com.qiniu.storage.Configuration(Zone.huadong());
            case "huabei":
                return new com.qiniu.storage.Configuration(Zone.huabei());
            case "huanan":
                return new com.qiniu.storage.Configuration(Zone.huanan());
            case "beimei":
                return new com.qiniu.storage.Configuration(Zone.beimei());
            default:
                throw new Exception("存储区域配置错误");
        }
    }

    /**
     * 构建一个七牛上传工具实例
     */
    @Bean
    public UploadManager uploadManager() throws Exception {
        return new UploadManager(qiNiuConfig());
    }

    /**
     * 认证信息实例
     */
    @Bean
    public Auth auth() {
        return Auth.create(accessKey, secretKey);
    }

    /**
     * 构建七牛空间管理实例
     */
    @Bean
    public BucketManager bucketManager() throws Exception {
        return new BucketManager(auth(), qiNiuConfig());
    }

    @Bean
    public Gson gson() {
        return new Gson();
    }
}

这里有个小细节,和SpringIOC有关的,那就是再Spring进行Bean命名的时候是按照驼峰命名发来的,也就是说,首字母一定会小写,那我们这个配置类的默认命名就和 qiNiuConfig() 这个Bean重复了,所以我们重新命了个名

然后来说下这段代码

switch (zone) {
            case "huadong":
                return new com.qiniu.storage.Configuration(Zone.huadong());
            case "huabei":
                return new com.qiniu.storage.Configuration(Zone.huabei());
            case "huanan":
                return new com.qiniu.storage.Configuration(Zone.huanan());
            case "beimei":
                return new com.qiniu.storage.Configuration(Zone.beimei());
            default:
                throw new Exception("存储区域配置错误");
        }

最开始我找到的时候只有国内的,没有国外的,然后我想到之前我使用Typora配置七牛云是,选择的是区域是As0,然后我就去Zone类里面找,还找到了

所以加上一句

case "xinjiapo":
                return new com.qiniu.storage.Configuration(Zone.xinjiapo());

以此类推,其他地区的应该也是缩写,大家自己改改就行

Service层

接口

package com.karos.td.Service;

import com.qiniu.common.QiniuException;

import java.io.File;
import java.io.InputStream;

public interface IQiniuService {

    /**
     * 以文件的形式上传
     *
     * @param file
     * @param fileName_fast 文件名
     * @param fileName_second 文件后缀
     * @return: java.lang.String
     */
    default String uploadFile(File file, String fileName_fast, String fileName_second) throws QiniuException {
        return null;
    }

    /**
     * 以流的形式上传
     *
     * @param inputStream
     * @param fileName_fast 文件名
     * @param fileName_second 文件后缀
     * @return: java.lang.String
     */
    String uploadFile(InputStream inputStream, String fileName_fast, String fileName_second) throws QiniuException;

    /**
     * 删除文件
     *
     * @param key:
     * @return: java.lang.String
     */
    String delete(String key) throws QiniuException;

}

对象

package com.karos.td.Service.impl;

import com.karos.td.Service.IQiniuService;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.UploadManager;
import com.qiniu.util.Auth;
import com.qiniu.util.StringMap;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.InputStream;

@Service
public class QiniuServiceImpl implements IQiniuService, InitializingBean {

    @Autowired
    private UploadManager uploadManager;

    @Autowired
    private BucketManager bucketManager;

    @Autowired
    private Auth auth;

    @Value("${qiniu.bucket}")
    private String bucket;

    @Value("${qiniu.domain}")
    private String domain;

    /**
     * 定义七牛云上传的相关策略
     */
    private StringMap putPolicy;

    @Override
    public String uploadFile(File file, String fileName_fast, String fileName_second) throws QiniuException {
        String fileName = fileName_fast + fileName_second;
        Response response = this.uploadManager.put(file, fileName, getUploadToken());
        int retry = 0;
        while (response.needRetry() && retry < 3) {
            response = this.uploadManager.put(file, fileName, getUploadToken());
            retry++;
        }
        if (response.statusCode == 200) {
            return "http://" + domain + "/" + fileName;
        }
        return "上传失败!";
    }

    @Override
    public String uploadFile(InputStream inputStream, String fileName_fast, String fileName_second) throws QiniuException {
        String fileName = fileName_fast + fileName_second;
        Response response = this.uploadManager.put(inputStream, fileName, getUploadToken(), null, null);
        int retry = 0;
        while (response.needRetry() && retry < 3) {
            response = this.uploadManager.put(inputStream, fileName, getUploadToken(), null, null);
            retry++;
        }
        if (response.statusCode == 200) {
            return "http://" + domain + "/" + fileName;
        }
        return "上传失败!";
    }


    @Override
    public String delete(String key) throws QiniuException {
        Response response = bucketManager.delete(this.bucket, key);
        int retry = 0;
        while (response.needRetry() && retry++ < 3) {
            response = bucketManager.delete(bucket, key);
        }
        return response.statusCode == 200 ? "删除成功!" : "删除失败!";
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        this.putPolicy = new StringMap();
        putPolicy.put("returnBody", "{\"key\":\"$(key)\",\"hash\":\"$(etag)\",\"bucket\":\"$(bucket)\",\"width\":$(imageInfo.width), \"height\":${imageInfo.height}}");
    }

    /**
     * 获取上传凭证
     */
    private String getUploadToken() {
        return this.auth.uploadToken(bucket, null, 3600, putPolicy);
    }

}

上传测试

    @Test
    void QiniuUpdate() throws QiniuException {
        //避免文件重名
        String res = qiniuService.uploadFile(new File("src/test/resources/test.txt"), UserSafetyUtil.touchCheckCode("test", "321"), ".txt");
        log.info("文件上传成功,文件地址为:" + res);
    }

为什么把文件类型专门提出来,就是懒得处理,或者你可以用

        int i = str.lastIndexOf(".");
        String sub=str.substring(i,res.length());

来获取扩展名,方法很多,另外这里我用了之前生成验证码的算法,避免名称重复,虽然也有一定重复的可能性,我的建议是你们自己写一个直接文件名+时间戳生成md5或者说直接用时间戳来命名也可以

比如这样

    @Test
    void QiniuUpdate() throws QiniuException {
        //避免文件重名
        String res = qiniuService.uploadFile(new File("src/test/resources/test.txt"), UserSafetyUtil.StrHex(new StringBuffer("test"), new StringBuffer(new Long(new Date().getTime()).toString())), ".txt");
        int i = res.lastIndexOf(".");
        String sub=res.substring(i,res.length());
        log.info("文件上传成功,文件地址为:" + res);
    }

上传测试

github地址

  • 微信或QQ扫一扫

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

目录