springboot集成七牛云上传文件

13 篇文章 0 订阅
8 篇文章 0 订阅

大体思路

上传

前端上传MultipartFile file 文件

进行名字空值校验和格式校验,大概就是判断后缀是不是属于jpg.png

生成唯一uuid名称,然后拿着这个文件名和图片文件File调接口

接口参数为

  • 输入流inputstream,将file化流传输
  • 文件名
  • 上传token,由access,secretKey,bucket生成,还可以指定过期时间,其他额外配置,该配置我们单独搞一个配置类注册bean后续注入即可

完事之后拼接url,https(fileAccess)+www.zzz.cn/47.11.11.1(domain)+文件名path丢给前端展示

这里上传失败还可以进行重重

删除

传文件名,bucket,调接口

代码如下

依赖

  <!--        七牛云依赖-->
        <dependency>
            <groupId>com.qiniu</groupId>
            <artifactId>qiniu-java-sdk</artifactId>
            <version>7.2.28</version>
        </dependency>

application.yml格式

# ========================== ↓↓↓↓↓↓ 七牛云配置 ↓↓↓↓↓↓ ==========================
qiniu:
  accessKey: xxxx
  secretKey: xxxx
  # 对象储存
  bucket: xxx # 空间名称
  zone: huanan # 存储区域
  domain: cdn.988.cn # 访问域名
  fileAccess: https://  没有ssl认证就http://

具体实现

service

package com.zww.service;

import com.qiniu.common.QiniuException;
import org.springframework.web.multipart.MultipartFile;

/**
 * @author pangpi
 */
public interface FileService {

    /**
     * 上传图片到OOS
     * @param img 上传的图片文件
     * @return 返回图片的链接路径
     */
    String uploadImg(MultipartFile img);

    String deleteImg(String key) throws QiniuException;
  
}

serviceImpl

package com.zww.service.impl;

import cn.hutool.core.util.ObjUtil;
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.zww.common.exception.ServiceException;
import com.zww.framework.enums.AppHttpCodeEnum;
import com.zww.framework.enums.FileTypeEnum;
import com.zww.service.FileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author pangpi
 */
@Slf4j
@Service
public class FileServiceImpl implements FileService {


    // @Autowired
    // private ApplicationContext applicationContext;
    @Value("${qiniu.fileUploadType}")
    private String fileUploadType;
    @Value("${qiniu.accessKey}")
    private String accessKey;

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

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

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

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

    // akey和skey在里面定义好了
    @Autowired
    private Auth auth;
    // 地区configuration在里面通过读取application.yml初始化好了
    @Autowired
    private UploadManager uploadManager;
    @Autowired
    private BucketManager bucketManager;



    // 这个方法就是在加工唯一文件名和校验用户上传的是否是图片格式后缀例如jpg,png
    @Override
    public String uploadImg(MultipartFile img) {
        // 判断文件类型,和文件大小
        // 获取原始文件名
        String originalFilename = img.getOriginalFilename();
        if (originalFilename == null) {
            throw new ServiceException("文件名不能为空");
            // throw new ServiceException(AppHttpCodeEnum.FILL_NAME_NOT_NULL.getMsg());
        }
        // 获取文件后缀
        String fileSuffix = getFileSuffix(originalFilename);
        // 判断后缀是否匹配img
        // if (checkImageSuffix(fileSuffix, FileTypeEnum.IMG.getFileType())) {
        if (checkImageSuffix(fileSuffix, "image")) {
            // throw new ServiceException(AppHttpCodeEnum.FILE_TYPE_ERROR.getMsg());
            throw new ServiceException("上传类型格式不为图片jpg,png...");
        }

        // 通过文件获取生成的文件路径
        // 根据日期生成路径   2022-1-15-
        // new一个日期格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-");
        // 通过格式器转换一个时间
        String datePath = sdf.format(new Date());
        // uuid作为文件名
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        // 后缀和文件后缀一致
        int index = originalFilename.lastIndexOf(".");
        // test.jpg -> .jpg
        String fileType = originalFilename.substring(index);
        String filePath = datePath + uuid + fileType;
        // 就是从test.jpg变成了2024-9-1-uuid32142343.jpg
        String url = uploadOss(img, filePath);
        return  url;
    }



    // 传入文件名然后调接口
    @Override
    public String deleteImg(String key) throws QiniuException {
        // 由于bucketManager注入了spring,且初始化了a,skey,和地区,所以可以直接传bucket调用
        // 如果有重传需求则三次重传
        Response response = bucketManager.delete(this.bucket, key);
        int retry = 0;
        while (response.needRetry() && retry++ < 3) {
            response = bucketManager.delete(this.bucket, key);
        }
        return response.statusCode == 200 ? "删除成功!" : "删除失败!";
    }

    /**
     * @param file     文件
     * @param filePath 文件路径
     * @return 文件访问url
     */
    // 如果你有别的oos,那么这里会动态获取bean并且上传
    // OosUploadService oosUploadService = applicationContext.getBean(fileUploadType + "_oos", OosUploadService.class);
    // if (ObjUtil.isNotEmpty(oosUploadService)) {
    //     return oosUploadService.uploadOss(file, filePath);
    // } else {
    //     log.error("对象存储 {} 不存在,请联系管理员",fileUploadType);
    //     throw new ServiceException(AppHttpCodeEnum.SYSTEM_ERROR.getMsg());
    // }
    // 这里直接使用qiniu_oss了,上传成功后返回字符串
    private String uploadOss(MultipartFile file, String filePath) {
        // 这里的getUploadToken()是获取上传凭证,由
        // Access Key: 访问密钥
        // Secret Key: 秘密密钥 和 存储空间名 bucket所生成
        // 同时还设置了令牌过期时间sxpire
        // 这两个密钥用于身份验证和权限控制,确保只有授权的用户可以访问或操作资源
        // 获取文件输入流
        try {
            // 将文件转为输入流,后面流给七牛云
            InputStream inputStream = file.getInputStream();
            try {
                //上传ing...
                Response response = this.uploadManager.put(inputStream, filePath, getUploadToken(), null, null);
                // 如果上一步执行没问题则说明上传完毕,此时给链接前端展示即可
                int retry = 0;
                // 如果有重传需求则三次重传
                while (response.needRetry() && retry < 3) {
                    response = this.uploadManager.put(inputStream, filePath, getUploadToken(), null, null);
                    retry++;
                }
                if (response.statusCode == 200) {
                    return fileAccess + domain + "/" + filePath;
                }
                return "上传失败";
            } catch (QiniuException e) {
                // 如果上传失败,捕获QiniuException并打印错误信息。
                System.err.println(e.response.toString());
                throw new RuntimeException(e);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

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

    /**
     * 输入文件名,获取文件的后缀
     *
     * @param fileName 文件名
     * @return 文件后缀
     */
    private String getFileSuffix(String fileName) {
        // 拆分文件和后缀
        String[] split = fileName.split("\\.");
        if (split.length <= 1) {
            throw new ServiceException(AppHttpCodeEnum.FILL_NAME_NOT_SUFFIX.getMsg());
        }
        return split[split.length - 1];
    }

    /**
     * 根据传入的后缀和文件类型,判断其后缀是否正常
     *
     * @param imgSuffix 文件类型
     * @return 是否满足后缀要求
     */
    private boolean checkImageSuffix(String imgSuffix, String fileType) {
        // 暂时使用set进行判断,后续有需要改为数据库动态存储不同文件类型下的文件后缀
        Map<String, Set<String>> fileTypeSuffixMap = new HashMap<>();
        // 每个文件类型存储多个后缀格式用set存放,最后放入map
        Set<String> imageSuffixName = new HashSet<>();
        imageSuffixName.add("jpg");
        imageSuffixName.add("jpeg");
        imageSuffixName.add("jpe");
        imageSuffixName.add("png");
        imageSuffixName.add("svg");
        imageSuffixName.add("webp");
        fileTypeSuffixMap.put(FileTypeEnum.IMG.getFileType(), imageSuffixName);

        Set<String> excelSuffixName = new HashSet<>();
        excelSuffixName.add("xlsx");
        excelSuffixName.add("xls");
        fileTypeSuffixMap.put(FileTypeEnum.EXCEL.getFileType(), excelSuffixName);

        Set<String> htmlSuffixName = new HashSet<>();
        htmlSuffixName.add("html");
        fileTypeSuffixMap.put(FileTypeEnum.HTML.getFileType(), htmlSuffixName);

        Set<String> mp3SuffixName = new HashSet<>();
        mp3SuffixName.add("mp3");
        fileTypeSuffixMap.put(FileTypeEnum.MP3.getFileType(), mp3SuffixName);

        Set<String> lrcSuffixName = new HashSet<>();
        lrcSuffixName.add("lrc");
        fileTypeSuffixMap.put(FileTypeEnum.LRC.getFileType(), lrcSuffixName);

        if (ObjUtil.isEmpty(fileTypeSuffixMap.get(fileType))) {
            log.error("没有这样一个类型: {} 存放在类型map中", fileType);
            return true;
        }
        return !(fileTypeSuffixMap.get(fileType).contains(imgSuffix));
    }

}

初始化配置类

package com.zww.framework.config;

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 com.zww.common.exception.GlobalException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class QiniuConfig {

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

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

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

    /**
     * 配置空间的存储区域
     */
    @Bean
    public com.qiniu.storage.Configuration qiNiuConfig() {
        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 GlobalException("存储区域配置错误");
        }
    }

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

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

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

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

}

测试代码

将本地图片File 对象转为multipartFile 然后调用方法

package com.zww;

import com.qiniu.common.QiniuException;
import com.zww.service.FileService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

@RunWith(SpringRunner.class)
@SpringBootTest
public class QiniuTest {

    @Autowired
    private FileService fileService;
    public static MultipartFile convert(File file) throws IOException {
        InputStream inputStream = new FileInputStream(file);
        return new MockMultipartFile("file", file.getName(), "image/jpeg", inputStream);
    }

    @Test
    public void testUpload() throws IOException {
        File file = new File("电脑图片链接xxxxx");
        MultipartFile multipartFile = convert(file);
        String result = fileService.uploadImg(multipartFile);
        System.out.println("访问地址: " + result);
    }

    @Test
    public void testDelete() throws QiniuException {
        String result = fileService.deleteImg("helloworld");
        System.out.println(result);
    }

}
使用File作为参数,不过得

image-20240831171250604

控制台输出

image-20240831171305444

当然你也可以上传其他文件类型例如视频,文本,压缩包,这里不过多赘述,原理大差不差,前端传好参数,后端参数好好填入就行,配置文件别写错

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现Spring Boot整合七牛云上传文件,可以按照以下步骤进行: 1.引入七牛云Java SDK 在pom.xml中引入七牛云Java SDK: ```xml <dependency> <groupId>com.qiniu</groupId> <artifactId>qiniu-java-sdk</artifactId> <version>[7.2.0,)</version> </dependency> ``` 2.配置七牛云参数 在application.yml或application.properties中添加七牛云的参数: ```yml qiniu: accessKey: your_access_key secretKey: your_secret_key bucket: your_bucket_name domain: your_domain_name ``` 3.编写上传文件的代码 在需要上传文件的地方编写上传文件的代码,示例代码如下: ```java @Service public class QiniuService { @Autowired private QiniuConfig qiniuConfig; /** * 上传文件七牛云 * * @param file 文件对象 * @return 文件访问URL */ public String uploadFile(File file) throws QiniuException { // 构造一个带指定Zone对象的配置类 Configuration cfg = new Configuration(Zone.autoZone()); // ...其他参数参考类注释 UploadManager uploadManager = new UploadManager(cfg); // 生成上传凭证,然后准备上传 String accessKey = qiniuConfig.getAccessKey(); String secretKey = qiniuConfig.getSecretKey(); String bucket = qiniuConfig.getBucket(); // 如果是Windows情况下,格式是 D:\\qiniu\\test.png String localFilePath = file.getAbsolutePath(); // 默认不指定key的情况下,以文件内容的hash值作为文件名 String key = null; Auth auth = Auth.create(accessKey, secretKey); String upToken = auth.uploadToken(bucket); try { Response response = uploadManager.put(localFilePath, key, upToken); // 解析上传成功的结果 DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class); return qiniuConfig.getDomain() + "/" + putRet.key; } catch (QiniuException ex) { Response r = ex.response; System.err.println(r.toString()); try { System.err.println(r.bodyString()); } catch (QiniuException ex2) { // ignore } throw ex; } } } ``` 4.测试上传文件 在测试类中编写测试上传文件的代码,示例代码如下: ```java @RunWith(SpringRunner.class) @SpringBootTest public class QiniuServiceTest { @Autowired private QiniuService qiniuService; @Test public void testUploadFile() throws QiniuException { File file = new File("test.png"); String url = qiniuService.uploadFile(file); System.out.println(url); } } ``` 其中,test.png是要上传的文件名。运行测试类即可上传文件七牛云,并返回文件的访问URL。 以上就是Spring Boot整合七牛云上传文件的全部步骤。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值