七牛存储sdk在springboot完美集成和应用 七牛依赖 自动化配置

文章目录

    • 概要
    • 依赖
    • 配置属性
    • 配置类
    • 配置文件
    • 业务层
    • 控制层
    • 运行结果
    • 亮点

概要

七牛存储很便宜的,在使用项目的用好官方封装好的sdk,结合springboot去使用很方便,我本地用的是springoot3+spring-boot-autoconfigure

依赖

<dependency><groupId>com.qiniu</groupId><artifactId>qiniu-java-sdk</artifactId><version>7.18.0</version>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-autoconfigure</artifactId>
</dependency>

配置属性


import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;/*** @author*/
@Data
@Slf4j
@ConfigurationProperties(prefix = "cc.qiniu")
public class QiNiuProperties {/*** host*/private String accessKey;/*** apiKey*/private String secretKey;/*** bucket*/private String bucket;/*** domain*/private String domain;}

配置类


import com.cc672cc.properties.QiNiuProperties;
import com.qiniu.storage.Region;
import com.qiniu.storage.UploadManager;
import com.qiniu.util.Auth;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class QiNiuConfig {@Autowiredprivate QiNiuProperties qiNiuProperties;@Beanpublic Auth auth() {return Auth.create(qiNiuProperties.getAccessKey(), qiNiuProperties.getSecretKey());}@Beanpublic com.qiniu.storage.Configuration configuration() {// todo  这里换上你自己的区域return new com.qiniu.storage.Configuration(Region.huadong());}@Beanpublic UploadManager uploadManager(com.qiniu.storage.Configuration cfg) {return new UploadManager(cfg);}@Beanpublic com.qiniu.storage.BucketManager bucketManager(com.qiniu.storage.Configuration cfg, Auth auth) {return new com.qiniu.storage.BucketManager(auth, cfg);}
}

配置文件

  cc:qiniu:access-key: 你的access-keysecret-key: 你的secret-keybucket: 你自己的bucket名字domain: 写上你自己的七牛存储访问的域名,系统自带的30天会过期,尽快绑定

业务层

public interface IQiNiuService {String uploadFile(MultipartFile file) throws IOException;String uploadFile(String filePath, String key) throws IOException;void deleteFile(String key) throws IOException;
}
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import com.cc672cc.properties.QiNiuProperties;
import com.cc672cc.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.storage.model.DefaultPutRet;
import com.qiniu.util.Auth;
import com.qiniu.util.StringMap;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;@Service
@Slf4j
public class QiNiuServiceImpl implements IQiNiuService {@Autowiredprivate UploadManager uploadManager;@Autowiredprivate BucketManager bucketManager;@Autowiredprivate Auth auth;@Autowiredprivate QiNiuProperties qiNiuProperties;// 图片文件扩展名列表private static final List<String> IMAGE_EXTS = Arrays.asList("jpg", "jpeg", "png", "gif", "bmp", "webp", "svg");// 视频文件扩展名列表private static final List<String> VIDEO_EXTS = Arrays.asList("mp4", "avi", "mov", "wmv", "flv", "mkv", "webm");/*** 上传文件到七牛云*/@Overridepublic String uploadFile(MultipartFile file) throws IOException {String originalFilename = file.getOriginalFilename();String key = generateHierarchicalKey(originalFilename);try {Response response = uploadManager.put(file.getBytes(), key, getUploadToken());DefaultPutRet putRet = response.jsonToObject(DefaultPutRet.class);return qiNiuProperties.getDomain() + "/" + putRet.key;} catch (QiniuException e) {Response r = e.response;throw new IOException("上传失败: " + r.toString(), e);}}/*** 上传本地文件到七牛云*/@Overridepublic String uploadFile(String filePath, String key) throws IOException {if (key == null) {// 从文件路径中提取文件名String fileName = filePath.substring(filePath.lastIndexOf("/") + 1);key = generateHierarchicalKey(fileName);}try {Response response = uploadManager.put(filePath, key, getUploadToken());DefaultPutRet putRet = response.jsonToObject(DefaultPutRet.class);return qiNiuProperties.getDomain() + "/" + putRet.key;} catch (QiniuException e) {Response r = e.response;throw new IOException("上传失败: " + r.toString(), e);}}/*** 生成带层级结构的文件键* 格式: {type}/{yyyy-MM-dd}/{random}*/private String generateHierarchicalKey(String originalFilename) {if (originalFilename == null) {return UUID.randomUUID().toString().replace("-", "");}// 获取文件扩展名String ext = getFileExtension(originalFilename).toLowerCase();// 确定文件类型目录String typeDir = getFileTypeDir(ext);// 获取当前日期目录String dateDir = DateUtil.format(new Date(), "yyyy-MM-dd");// 生成随机文件名String randomName = UUID.randomUUID().toString().replace("-", "");// 组合完整路径return typeDir + "/" + dateDir + "/" + randomName + "." + ext;}/*** 获取文件扩展名*/private String getFileExtension(String filename) {int dotIndex = filename.lastIndexOf('.');if (dotIndex == -1) {return "";}return filename.substring(dotIndex + 1);}/*** 根据文件扩展名确定文件类型目录*/private String getFileTypeDir(String ext) {if (IMAGE_EXTS.contains(ext)) {return "images";} else if (VIDEO_EXTS.contains(ext)) {return "videos";} else {return "others";}}/*** 删除七牛云存储的文件** @param key 文件键* @throws IOException 删除失败时抛出异常*/@Overridepublic void deleteFile(String key) throws IOException {try {bucketManager.delete(qiNiuProperties.getBucket(), key);} catch (QiniuException e) {Response r = e.response;throw new IOException("删除失败: " + r.toString(), e);}}/*** 生成私有空间文件的临时访问URL** @param key           文件键* @param expireSeconds 过期时间(秒)* @return 临时访问URL*/public String generatePrivateDownloadUrl(String key, long expireSeconds) {return auth.privateDownloadUrl(qiNiuProperties.getBucket() + "/" + key, expireSeconds);}/*** 获取上传凭证*/private String getUploadToken() {return auth.uploadToken(qiNiuProperties.getBucket());}/*** 获取带回调的上传凭证*/public String getUploadTokenWithCallback(String callbackUrl, String callbackBody) {return auth.uploadToken(qiNiuProperties.getBucket(), null, 3600, new StringMap().put("callbackUrl", callbackUrl).put("callbackBody", callbackBody));}
}

控制层

@RestController
@Slf4j
@Tag(name = "开放七牛控制器", description = "测试接口")
@RequestMapping("/open/qiniu")
public class OpenQiNiuController {@Autowiredprivate IQiNiuService qiNiuService;@PostMapping("/upload")@Operation(summary = "上传文件")public String upload(@RequestParam("file") MultipartFile file) throws IOException {return qiNiuService.uploadFile(file);}
}

运行结果

{"code": 0,"message": "success","data": "http://qiniu.cc672.xyz/images/2025-06-17/0617cd177f264f938f7666b95a8698cf.jpg"
}

上传结果

亮点

  • 快捷
  • 自定义三级目录

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java相关-链表-设计链表-力扣707

你可以选择使用单链表或者双链表&#xff0c;设计并实现自己的链表。 单链表中的节点应该具备两个属性&#xff1a;val 和 next 。val 是当前节点的值&#xff0c;next 是指向下一个节点的指针/引用。 如果是双向链表&#xff0c;则还需要属性 prev 以指示链表中的上一个节点…

C# 关于LINQ语法和类型的使用

常用语法&#xff0c;具体问题具体分析 1. Select2. SelectMany3. Where4. Take5. TakeWhile6. SkipWhile7. Join8. GroupJoin9. OrderBy10. OrderByDescending11. ThenBy12. Concat13. Zip14. Distinct15. Except16. Union17. Intersect18. Concat19. Reverse20. SequenceEqua…

华为OD-2024年E卷-小明周末爬山[200分] -- python

问题描述&#xff1a; 题目描述 周末小明准备去爬山锻炼&#xff0c;0代表平地&#xff0c;山的高度使用1到9来表示&#xff0c;小明每次爬山或下山高度只能相差k及k以内&#xff0c;每次只能上下左右一个方向上移动一格&#xff0c;小明从左上角(0,0)位置出发 输入描述 第一行…

Android:使用OkHttp

1、权限&#xff1a; <uses-permission android:name"android.permission.INTERNET" /> implementation com.squareup.okhttp3:okhttp:3.4.1 2、GET&#xff1a; new XXXTask ().execute("http://192.168.191.128:9000/xx");private class XXXTask…

Vue3+Element Plus动态表格列宽设置

在 Vue3 Element Plus 中实现动态设置表格列宽&#xff0c;可以通过以下几种方式实现&#xff1a; 方法 1&#xff1a;动态绑定 width 属性&#xff08;推荐&#xff09; vue 复制 下载 <template><el-table :data"tableData" style"width: 100%…

【JVM目前使用过的参数总结】

JVM参数总结 笔记记录 JVM-栈相关JVM-方法区(元空间)相关JVM-堆相关 JVM-栈相关 .-XX:ThreadStackSize1M -Xss1m 上面的简写形式【设置栈的大小】 JVM-方法区(元空间)相关 -XX:MaxMetaspaceSize10m 【设置最大元空间大小】 JVM-堆相关 -XX:MaxHeapSize10m -Xmx10m 上面的简写形…

AI辅助高考志愿填报-专业全景解析与报考指南

高考志愿填报&#xff0c;这可是关系到孩子未来的大事儿&#xff01;最近&#xff0c;我亲戚家的孩子也面临着这个难题&#xff0c;昨晚一个电话就跟我聊了好久&#xff0c;问我报啥专业好。说实话&#xff0c;这问题真不好回答&#xff0c;毕竟每个孩子情况不一样&#xff0c;…

Android Studio Windows安装与配置指南

Date: 2025-06-14 20:07:12 author: lijianzhan 内容简介 文章中&#xff0c;主要是为了初次接触 Android 开发的用户提供详细的关于 Android Studio 安装以及配置教程&#xff0c;涵盖环境准备、软件下载、安装配置全流程&#xff0c;重点解决路径命名、组件选择、工作空间设置…

SpringAI+DeepSeek-了解AI和大模型应用

一、认识AI 1.人工智能发展 AI&#xff0c;人工智能&#xff08;Artificial Intelligence&#xff09;&#xff0c;使机器能够像人类一样思考、学习和解决问题的技术。 AI发展至今大概可以分为三个阶段&#xff1a; 其中&#xff0c;深度学习领域的自然语言处理(Natural Lan…

IP5362至为芯支持无线充的22.5W双C口双向快充移动电源方案芯片

英集芯IP5362是一款应用于移动电源&#xff0c;充电宝&#xff0c;手机&#xff0c;平板电脑等支持无线充模式的22.5W双向快充移动电源方案SOC芯片,集成同步升降压转换器、锂电池充电管理、电池电量指示等功能。兼容全部快充协议&#xff0c;同步开关放电支持最大22.5W输出功率…

手游刚开服就被攻击怎么办?如何防御DDoS?

手游新上线时遭遇DDoS攻击是常见现象&#xff0c;可能导致服务器瘫痪、玩家流失甚至项目失败。面对突如其来的攻击&#xff0c;开发者与运营商需要迅速响应并建立长效防御机制。本文提供应急处理步骤与防御策略&#xff0c;助力游戏稳定运营。 一、手游开服遭攻击的应急响应 快…

秋招是开发算法一起准备,还是只准备一个

THE LAST TIME 昨天晚上半夜有个星球的26届的同学&#xff0c;私信问我。说目前是只准备开发还是开发算法一起准备&#xff08;两者技术知识都挺欠缺的&#xff09; 看到这里&#xff0c;肯定有很多同学会说。马上都该秋招了&#xff0c;还什么多线程开工&#xff0c;赶紧能住编…

web项目部署配置HTTPS遇到的问题解决方法

今天使用nginxtomcatssl完成了web项目的部署&#xff0c;本以为没有什么问题&#xff0c;但是在页面测试的时候又蹦出了这么一个问题&#xff0c;大致是说由于配置了HTTPS&#xff0c;但是之前的请求是通过HTTP请求的&#xff0c;所以现在被拦截&#xff0c;由于缺少某些权限信…

理解与建模弹性膜-AI云计算数值分析和代码验证

弹性膜在连接生物学理解和工程创新方面至关重要&#xff0c;因为它们能够模拟软组织力学、实现先进的细胞培养系统和促进柔性设备&#xff0c;广泛应用于软组织生物力学、细胞培养、生物膜建模和生物医学工程等领域。 ☁️AI云计算数值分析和代码验证 弹性膜在连接生物学理解和…

AI大模型竞赛升温:百度发布文心大模型4.5和X1

AI大模型&#xff0c;作为智能技术的巅峰之作&#xff0c;正逐步改变着我们的生活与工作方式。近期&#xff0c;百度在AI大模型领域的最新动向&#xff0c;无疑为这场科技竞赛再添一把火。3月16日&#xff0c;百度正式宣布发布文心大模型4.5及文心大模型X1&#xff0c;这两款大…

升级OpenSSL和OpenSSH 修复漏洞

升级OpenSSL和OpenSSH 目前版本OpenSSH_7.4p1, OpenSSL 1.0.2k-fips 26 Jan 2017 升级到OpenSSH_9.8p1, OpenSSL 1.1.1u 30 May 2023 服务器CentOS Linux release 7.6.1810 (Core) 一、升级OpenSSL到1.1.1u 下载并编译 OpenSSL&#xff08;推荐目录 /usr/local/openssl&…

JavaSE - Object 类详细讲解

定义 是所有类的直接或者间接父类&#xff0c;是 Java 中唯一一个没有父类的类。其中所有的方法都是可以被子类继承的。 常用方法 equals方法&#xff1a; 比较两个对象引用的地址值是否相同&#xff0c;默认情况下是使用 “” 进行比较&#xff0c;但是这个方法一般会被之类…

观远ChatBI|让数据分析像聊天一样简单

BI通过收集、整合和分析企业内部的各种数据&#xff0c;帮助企业发现数据中的模式和趋势&#xff0c;从而做出更明智的商业决策&#xff0c;以此来提升企业的经营能力和竞争力。无论是传统BI还是自助BI&#xff0c;都是为了在数据和人之间建立一座桥梁&#xff0c;使数据能够被…

Go语言同步原语与数据竞争:WaitGroup

在Go语言并发编程中&#xff0c;我们经常需要等待多个 goroutine 执行完毕后再继续下一步操作。Go 提供的 sync.WaitGroup 就是专为这种**“等待一组任务完成”**而设计的同步原语。 一、基本原理 sync.WaitGroup 提供三个主要方法&#xff1a; 方法说明Add(n int)设置等待的…

Java单体架构 vs 分布式架构

Java单体架构 vs 分布式架构 在电商系统开发中&#xff0c;当用户量从几百激增到百万级&#xff0c;你的架构是否还能从容应对&#xff1f;一次代码更新是否意味着整个系统停机&#xff1f;今天我们就来拆解Java架构设计的核心命题&#xff1a;单体还是分布式&#xff1f; 一、…