AWS S3文件存储工具类
pom依赖
<!--aws-s3-->
<dependency><groupId>com.amazonaws</groupId><artifactId>aws-java-sdk-s3</artifactId><version>1.12.95</version></dependency>
S3Utils
import cn.hutool.core.util.ZipUtil;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.*;
import com.crm.common.config.S3Config;
import com.crm.common.enums.ConflictPolicy;
import com.crm.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.LinkedList;
import java.util.List;@Component
public class S3Utils {private BasicAWSCredentials awsCreds = null;private AmazonS3 s3 = null;@AutowiredS3Config s3Config;@PostConstructpublic void init() {/*** 创建s3对象*/if (StringUtils.isNotBlank(s3Config.getAccessKey()) && StringUtils.isNotBlank(s3Config.getSecretKey())) {ClientConfiguration config = new ClientConfiguration();AwsClientBuilder.EndpointConfiguration endpointConfig =new AwsClientBuilder.EndpointConfiguration(s3Config.getEndpoint(), "cn-north-1");awsCreds = new BasicAWSCredentials(s3Config.getAccessKey(), s3Config.getSecretKey());s3 = AmazonS3ClientBuilder.standard().withEndpointConfiguration(endpointConfig).withClientConfiguration(config).withCredentials(new AWSStaticCredentialsProvider(awsCreds)).build();}}/*** 上传文件** @param file 文件*/public String uploadFile(MultipartFile file, String moduleName) {return uploadFile(file, ConflictPolicy.NEW, moduleName);}/*** @param file* @param policy 冲突策略,当同一路径下有同名文件时可选。默认是替换同名文件* @param moduleName 项目内的模块名* @return*/public String uploadFile(MultipartFile file, ConflictPolicy policy, String moduleName) {if (isEmpty(file)) {return null;}// 生成临时文件File localFile = null;try {//先从s3服务器上查找是否有同名文件String key = s3Config.getProject() + "/" + moduleName + "/" + file.getOriginalFilename();localFile = File.createTempFile("temp", null);file.transferTo(localFile);String prefix = key.substring(0, key.lastIndexOf("."));String suffix = key.substring(key.indexOf("."));//取出同名文件的最大numberint maxNum = getMaxVersionNum(s3Config.getBucketName(), prefix, suffix);if (maxNum != -1) {switch (policy) {case NEW:key = prefix + "(" + (++maxNum) + ")" + suffix;break;case RETAIN:return "文件已存在,根据冲突策略,文件不予替换";case REPLACE:default:break;}}PutObjectRequest request = new PutObjectRequest(s3Config.getBucketName(), key, localFile);// 上传文件 如果没抛异常则可认为上传成功PutObjectResult putObjectResult = s3.putObject(request);if (StringUtils.isNotEmpty(putObjectResult.getETag())) {return key;}return null;} catch (IOException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();} finally {if (localFile != null) {localFile.delete();}}return null;}private int getMaxVersionNum(String bucketName, String prefix, String suffix) {ListObjectsRequest listRequest = new ListObjectsRequest().withBucketName(bucketName).withPrefix(prefix).withMaxKeys(100);ObjectListing objectListing = s3.listObjects(listRequest);int value = -1;for (S3ObjectSummary inst : objectListing.getObjectSummaries()) {String indexStr = inst.getKey().replace(prefix, "").replace("(", "").replace(")", "").replace(suffix, "");if (indexStr.length() == 0) {indexStr = "0";}value = Math.max(value, Integer.parseInt(indexStr));}return value;}/*** 删除单个文件** @param key 根据key删除文件* @return*/public void deleteObject(String key) {if (StringUtils.isBlank(key)) {throw new IllegalArgumentException("key can not be null");}s3.deleteObject(s3Config.getBucketName(), key);}/*** @param key 根据key得到文件的输入流* @return*/public S3ObjectInputStream getFileInputStream(String key) {S3Object object = s3.getObject(new GetObjectRequest(s3Config.getBucketName(), key));return object.getObjectContent();}/*** 根据key得到输入流并输出到输出流** @param key* @param stream*/public void downloadFile(String key, OutputStream stream) {InputStream input = getFileInputStream(key);byte[] data = null;try {data = new byte[input.available()];int len = 0;while ((len = input.read(data)) != -1) {stream.write(data, 0, len);}} catch (IOException e) {e.printStackTrace();} finally {if (stream != null) {try {stream.close();} catch (IOException e) {e.printStackTrace();}}if (input != null) {try {input.close();} catch (IOException e) {e.printStackTrace();}}}}/*** 根据key得到输入流并输出到输出流** @param key* @param response*/public void downloadFile(String key, HttpServletResponse response) {String fileName = key;byte[] data = null;OutputStream stream = null;InputStream input = getFileInputStream(key);if (key.contains("/")) {String[] path = key.split("/");fileName = path[path.length - 1];}response.setHeader("Content-Disposition", "attachment; filename=" + fileName);try {stream = response.getOutputStream();data = new byte[input.available()];int len = 0;while ((len = input.read(data)) != -1) {stream.write(data, 0, len);}} catch (IOException e) {e.printStackTrace();} finally {if (stream != null) {try {stream.close();} catch (IOException e) {e.printStackTrace();}}if (input != null) {try {input.close();} catch (IOException e) {e.printStackTrace();}}}}/*** 删除文件夹** @param filePath 文件夹地址[ eg:temp/1 或 temp ]* @param deleteAll true-递进删除所有文件(包括子文件夹);false-只删除当前文件夹下的文件,不删除子文件夹内容*/public void deleteFolder(String filePath, boolean deleteAll) {ListObjectsV2Request objectsRequest = new ListObjectsV2Request();objectsRequest.setBucketName(s3Config.getBucketName());objectsRequest.setPrefix(filePath);// deliter表示分隔符, 设置为/表示列出当前目录下的object, 设置为空表示列出所有的objectobjectsRequest.setDelimiter(deleteAll ? "" : "/");// 设置最大遍历出多少个对象, 一次listobject最大支持1000objectsRequest.setMaxKeys(1000);ListObjectsV2Result listObjectsRequest = s3.listObjectsV2(objectsRequest);List<S3ObjectSummary> objects = listObjectsRequest.getObjectSummaries();String[] object_keys = new String[objects.size()];for (int i = 0; i < objects.size(); i++) {S3ObjectSummary item = objects.get(i);object_keys[i] = item.getKey();}DeleteObjectsRequest dor = new DeleteObjectsRequest(s3Config.getBucketName()).withKeys(object_keys);s3.deleteObjects(dor);}/*** 检查文件是否为空** @param* @return*/public boolean isEmpty(MultipartFile file) {if (file == null || file.getSize() <= 0) {return true;}return false;}/*** 得到所有文件的key** @return key list*/public List<String> getFileKeys() {List<String> keys = new LinkedList<>();ListObjectsRequest listRequest = new ListObjectsRequest().withBucketName(s3Config.getBucketName());try {ObjectListing objects = s3.listObjects(listRequest);while (true) {List<S3ObjectSummary> summaries = objects.getObjectSummaries();for (S3ObjectSummary summary : summaries) {keys.add(summary.getKey());}if (objects.isTruncated()) {objects = s3.listNextBatchOfObjects(objects);} else {break;}}} catch (Exception exception) {exception.printStackTrace();}return keys;}public void getBizFile(List<String> keys, File targetZipFile) {InputStream[] inputStreams = keys.stream().map(this::getFileInputStream).toArray(InputStream[]::new);String[] strings = keys.stream().map(key -> key.split("/")[key.split("/").length - 1]).toArray(String[]::new);ZipUtil.zip(targetZipFile, strings, inputStreams);}public void downBizFile(List<String> keys, HttpServletResponse response) {File file = new File(System.currentTimeMillis() + ".zip");getBizFile(keys, file);OutputStream toClient = null;try {// 以流的形式下载文件。BufferedInputStream fis = new BufferedInputStream(new FileInputStream(file.getPath()));byte[] buffer = new byte[fis.available()];fis.read(buffer);fis.close();// 清空responseresponse.reset();toClient = new BufferedOutputStream(response.getOutputStream());response.setCharacterEncoding("UTF-8");response.setContentType("application/octet-stream");response.setHeader("Content-Disposition", "attachment;filename=" + file.getName());toClient.write(buffer);toClient.flush();} catch (Exception e) {e.printStackTrace();} finally {if (toClient != null) {try {toClient.close();} catch (IOException e) {e.printStackTrace();}}//删除改临时zip包(此zip包任何时候都不需要保留,因为源文件随时可以再次进行压缩生成zip包)file.delete();}}}
相关配置类
public enum ConflictPolicy {REPLACE, NEW, RETAIN
}@Component
@ConfigurationProperties(prefix="aws.s3")
public class S3Config {private String accessKey;private String secretKey;private String bucketName;private String region;private String project;private String module;private String endpoint;public String getEndpoint() {return endpoint;}public void setEndpoint(String endpoint) {this.endpoint = endpoint;}public String getModule() {return module;}public void setModule(String module) {this.module = module;}public String getAccessKey() {return accessKey;}public void setAccessKey(String accessKey) {this.accessKey = accessKey;}public String getSecretKey() {return secretKey;}public void setSecretKey(String secretKey) {this.secretKey = secretKey;}public String getBucketName() {return bucketName;}public void setBucketName(String bucketName) {this.bucketName = bucketName;}public String getRegion() {return region;}public void setRegion(String region) {this.region = region;}public String getProject() {return project;}public void setProject(String project) {this.project = project;}
}aws:s3:endpoint: https://s3-xxxxx.comaccessKey: xxxxxsecretKey: xxxxbucketName: xxxregion: cn-north-1project: xxxmodule: dev
相关文章:
AWS S3文件存储工具类
pom依赖 <!--aws-s3--> <dependency><groupId>com.amazonaws</groupId><artifactId>aws-java-sdk-s3</artifactId><version>1.12.95</version></dependency>S3Utils import cn.hutool.core.util.ZipUtil; import com.a…...

【leetcode100】二叉树的中序遍历
1、题目描述 给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。 示例 1: 输入:root [1,null,2,3] 输出:[1,3,2] 2、初始思路 2.1 思路 中序遍历的顺序是左→根→右,定义一个函数进行遍历 # Definition for …...
开源GTKSystem.Windows.Forms框架:C# Winform跨平台运行深度解析
开源GTKSystem.Windows.Forms框架:C# Winform跨平台运行深度解析 一、跨平台框架的崛起 1.1 跨平台技术的现状与需求 在当今快速发展的科技时代,软件开发的需求日益多样化。随着移动设备和操作系统的不断涌现,开发者面临着前所未有的挑战&…...
C++软件设计模式之责任链模式
责任链模式的动机与意图 动机: 在软件开发中,经常会遇到需要处理一系列请求或事件的情况。这些请求可能需要经过多个处理对象,每个对象根据其职责决定是否处理请求或将其传递给下一个对象。责任链模式(Chain of Responsibility P…...

021-spring-springmvc-组件
SpringMVC的handMapping 比较重要的部分 比较重要的部分 比较重要的部分 关于组件的部分 这里以 RequestMappingHandlerMapping 为例子 默认的3个组件是: org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping org.springframework.web.servlet.mvc…...

基于SpringBoot和OAuth2,实现通过Github授权登录应用
基于SpringBoot和OAuth2,实现通过Github授权登录应用 文章目录 基于SpringBoot和OAuth2,实现通过Github授权登录应用0. 引言1. 创建Github应用2. 创建SpringBoot测试项目2.1 初始化项目2.2 设置配置文件信息2.3 创建Controller层2.4 创建Html页面 3. 启动…...

macos 支持外接高分辩率显示器开源控制软件
macos 支持外接高分辩率显示器开源控制软件 软件(app应用)名:BetterDisplay 官方地址: https://github.com/waydabber/BetterDisplay...
C++26 新特性预览(Preview)
文章目录 1. 静态反射 (Static Reflection)示例: 枚举转字符串应用场景 2. 合约 (Contracts)示例: 定义函数合约应用场景 3. 条件中的结构化绑定 (Structured Bindings in Conditions)示例: 改进的错误处理应用场景 4. 包索引 (Pack Indexing)示例: 获取参数包的第一个和最后一…...

MySQL5.7.26-Linux-安装(2024.12)
文章目录 1.下载压缩包1.访问MySQL版本归档2.找到5.7.26并下载3.百度网盘 2.Linux安装1.卸载原来的MySQL8.0.26(如果没有则无需在意)1.查看所有mysql的包2.批量卸载3.删除残留文件**配置文件**(默认路径): 4.**验证卸载…...

2025-1-2-sklearn学习(30)模型选择与评估-验证曲线: 绘制分数以评估模型 真珠帘卷玉楼空,天淡银河垂地。
文章目录 sklearn学习(30) 模型选择与评估-验证曲线: 绘制分数以评估模型30.1. 验证曲线30.2. 学习曲线 sklearn学习(30) 模型选择与评估-验证曲线: 绘制分数以评估模型 文章参考网站: https://sklearn.apachecn.org/ 和 https://scikit-learn.org/stable/ 每种估…...

【优选算法】查找总价格为目标值的两个商品
链接:LCR 179. 查找总价格为目标值的两个商品 - 力扣(LeetCode) 解法:利用单调性,使用双指针算法解决问题 1.先从小到大排序 2. sum > t : right--; sum < t : left; sum t : return class Solution {public…...

利用 NineData 实现 PostgreSQL 到 Kafka 的高效数据同步
记录一次 PostgreSQL 到 Kafka 的数据迁移实践。前段时间,NineData 的某个客户在一个项目中需要将 PostgreSQL 的数据实时同步到 Kafka。需求明确且普遍: PostgreSQL 中的交易数据,需要实时推送到 Kafka,供下游多个系统消费&#…...
future和CompletableFuture
future 什么是future Future 类是并发编程中一个非常重要的工具。它主要用于表示一个异步计算的结果,允许你在计算完成后获取结果或处理异常。Java 的 Future 也常常与线程池(如 ExecutorService)结合使用,用来执行并行任务&…...

如何通过深度学习提升大分辨率图像预测准确率?
随着科技的不断进步,图像处理在各个领域的应用日益广泛,特别是在医疗影像、卫星遥感、自动驾驶、安防监控等领域中,大分辨率图像的使用已经成为了一项不可或缺的技术。然而,大分辨率图像带来了巨大的计算和存储压力,同…...
【机器学习】机器学习的基本分类-半监督学习-Ladder Networks
Ladder Networks 是一种半监督学习模型,通过将无监督学习与监督学习相结合,在标记数据较少的情况下实现高效的学习。它最初由 A. Rasmus 等人在 2015 年提出,特别适合深度学习任务,如图像分类或自然语言处理。 核心思想 Ladder N…...

[react]小技巧, ts如何声明点击事件的类型
很简单, 鼠标放到事件上面就行了 如果想知道点击的是什么元素 ,打印他的nodename就行了 不过得断言为html元素才行 const handleClick (e: React.MouseEvent<HTMLDivElement, MouseEvent>) > {console.log(current, (e.target as HTMLElement).nodeName);}; 为什么…...
智能工厂的设计软件 应用场景的一个例子:为AI聊天工具添加一个知识系统 之9 重新开始 之2
本文要点 对程序设计而言:前者基于一个自上而下的 分类体系--(生物遗传基因),后者者需要一个收集差异的自下而上的差异继承路径--(系统继承源流) 就是 广义和狭义 分类学。 共性对齐 和 差异收集 正是两者…...

【从零开始】11. LLaMA-Factory 微调 Qwen 模型(番外篇)
书接上回,在完成了 RAGChecker 测试后,离 RAG 应用真正发布还差最后一步 - 基础信息指令微调。考虑到模型还是需要具备一定程度的“自我认知”,因此需要将公司信息“嵌入”到模型里面的。为此,我选择了 LLaMA-Factory(…...

WPF使用ContentControl控件实现区域导航,并使用Prism依赖注入优化
背景:使用ContentControl控件实现区域导航是有Mvvm框架的WPF都能使用的,不限于Prism 主要是将ContenControl控件的Content内容在ViewModel中切换成不同的用户控件 下面是MainViewModel: private object body;public object Body {get { retu…...

JavaWeb——MySQL-DML(1/3)-添加数据insert(DML 操作概述、INSERT 语句插入数据、语句演示、总结)
目录 DML 操作概述 INSERT 语句插入数据 INSERT 语句基础语法 INSERT 语句演示 注意事项 总结 DML 操作概述 DML 简介 DML(Data Manipulation Language)即数据操作语言,用于对数据库表中的数据进行增删改操作,包括添加数据&…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...
【生成模型】视频生成论文调研
工作清单 上游应用方向:控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
Go语言多线程问题
打印零与奇偶数(leetcode 1116) 方法1:使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...

数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !
我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…...

AxureRP-Pro-Beta-Setup_114413.exe (6.0.0.2887)
Name:3ddown Serial:FiCGEezgdGoYILo8U/2MFyCWj0jZoJc/sziRRj2/ENvtEq7w1RH97k5MWctqVHA 注册用户名:Axure 序列号:8t3Yk/zu4cX601/seX6wBZgYRVj/lkC2PICCdO4sFKCCLx8mcCnccoylVb40lP...

MySQL体系架构解析(三):MySQL目录与启动配置全解析
MySQL中的目录和文件 bin目录 在 MySQL 的安装目录下有一个特别重要的 bin 目录,这个目录下存放着许多可执行文件。与其他系统的可执行文件类似,这些可执行文件都是与服务器和客户端程序相关的。 启动MySQL服务器程序 在 UNIX 系统中,用…...

echarts使用graphic强行给图增加一个边框(边框根据自己的图形大小设置)- 适用于无法使用dom的样式
pdf-lib https://blog.csdn.net/Shi_haoliu/article/details/148157624?spm1001.2014.3001.5501 为了完成在pdf中导出echarts图,如果边框加在dom上面,pdf-lib导出svg的时候并不会导出边框,所以只能在echarts图上面加边框 grid的边框是在图里…...