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

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

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

相关文章

深入剖析MySQL数据库架构:核心组件、存储引擎与优化策略(一)

sql语句分为两大类&#xff1a;查询&#xff08;select&#xff09;、增删改----修改&#xff08;update&#xff09; select语句的执行流程 执行sql语句的流程&#xff1a;连接数据库、缓存查询、解析器、优化器、执行器、存储引擎操作数据 客户端&#xff1a;图形界面工具…

【AimRT】现代机器人通信中间件 AimRT

目录 一、什么是AimRT二、AimRT与ROS22.1 定位与设计2.2 组成与通信方式对比 三、AimRT基本概念3.1 Node、Pkg 和 Module3.2 Protocol、Channel、Rpc 和 Filter3.3 App模式 和 Pkg模式3.4 Executor3.5 Plugin 一、什么是AimRT AimRT 是智元机器人公司自主研发的一款机器人通信…

SSM-Spring-AOP

目录 1 AOP实现步骤&#xff08;以前打印当前系统的时间为例&#xff09; 2 AOP工作流程 3 AOP核心概念 4 AOP配置管理 4-1 AOP切入点表达式 4-1-1 语法格式 4-1-2 通配符 4-2 AOP通知类型 五种通知类型 AOP通知获取数据 获取参数 获取返回值 获取异常 总结 5 …

idea( 2022.3.2)打包报错总结

一 报错 class lombok.javac.apt.LombokProcessor (in unnamed module 0x4fe64d23) cannot access class com.sun.tools.javac.processing.JavacProcessingEnvironment (in module jdk.compiler) because module jdk.compiler does not export com.sun.tools.javac.processing …

攻防靶场(29):目录权限和文件权限 ICMP

目录 1. 侦查 1.1 收集目标网络信息&#xff1a;IP地址 1.2 主动扫描&#xff1a;扫描IP地址段 1.3 搜索目标网站 2. 初始访问 2.1 利用面向公众的应用 3. 权限提升 3.1 有效账户&#xff1a;本地账户 3.2 滥用特权控制机制&#xff1a;Sudo和Sudo缓存 靶场下载地址&#xff1a…

C++ 面向对象编程:多态、虚函数原理

多态的通用描述便是&#xff0c;使用父类指针调用函数&#xff0c;可以根据对象类型来调用对应类型函数&#xff0c;我们分几个步骤来理解&#xff0c;先看下类的占用空间&#xff0c;然后拓展到虚函数对应数组&#xff0c;最后理解多态的原理。 我们先来看下在多态中没有任何…

王老吉药业SRM系统上线 携手隆道共启战略合作新篇章

12月27日&#xff0c;广州王老吉药业股份有限公司&#xff08;简称“王老吉药业”&#xff09;SRM项目上线启动会&#xff0c;在王老吉科普教育基地——“吉园”隆重举行。广药集团纪委主任陈耕、王老吉药业总工程师黄晓丹、隆道公司总裁吴树贵、项目经理赵耀、供应商代表郭伟及…

JavaScript基础 -- 变量、作用域与内存

1 原始值与引用值 原始值就是最简单的数据&#xff0c;引用值则是由多个值构成的对象。在把一个值赋给变量时&#xff0c;JavaScript引擎必须要确定这个值是原始值还是引用值 原始值大小固定&#xff0c;保存在栈内存上&#xff1b;引用值是对象&#xff0c;存储在堆内存上 它…

SQL—替换字符串—replace函数用法详解

SQL—替换字符串—replace函数用法详解 REPLACE() 函数——查找一个字符串中的指定子串&#xff0c;并将其替换为另一个子串。 REPLACE(str, old_substring, new_substring)str&#xff1a;要进行替换操作的原始字符串。old_substring&#xff1a;要被替换的子串。new_substri…

[极客大挑战 2019]Http 1

进入环境&#xff1a; 检查源码发现有一个链接&#xff0c;但是这里没有绑定&#xff0c;需要手动跳转&#xff0c;打开后&#xff0c;发现提示&#xff1a; 这里就是需要我们从https://Sycsecret.buuoj.cn来访问它 因此我们抓包&#xff0c;使用referer&#xff1a;服务器伪造…

吾杯网络安全技能大赛——Misc方向WP

吾杯网络安全技能大赛——Misc方向WP Sign 题目介绍: 浅浅签个到吧 解题过程&#xff1a; 57754375707B64663335376434372D333163622D343261382D616130632D3634333036333464646634617D 直接使用赛博橱子秒了 flag为 WuCup{df357d47-31cb-42a8-aa0c-6430634ddf4a} 原神启动…

如何查看下载到本地的大模型的具体大小?占了多少存储空间:Llama-3.1-8B下载到本地大概15GB

这里介绍一下tree命令&#xff0c;可以方便的查看文件目录结构和文件大小。 命令行tree的具体使用&#xff0c;请参考笔者的另一篇博客&#xff1a;深入了解 Linux tree 命令及其常用选项&#xff1a;Linux如何显示目录结构和文件大小&#xff0c;一言以蔽之&#xff0c;sudo a…

【Java回顾】Day2 正则表达式----异常处理

参考资料&#xff1a;菜鸟教程 https://www.runoob.com/java/java-exceptions.html 正则表达式 有一部分没看完 介绍 字符串的模式搜索、编辑或处理文本java.util.regex包&#xff0c;包含了pattern和mathcer类&#xff0c;用于处理正则表达式的匹配操作。 捕获组 把多个字符…

招银网路Java后端一面,难度有点大!

这是一位武汉理工大学同学的招银网络一面面经,同样附带超详细的参考答案。大家可以用来查漏补缺,针对性地补短板。 招银网络一面还是比较简单的,基本都是一些比较重要且高频的常规八股,项目问的不多。到了二面的时候, 会开始主要考察你的项目。 1、自我介绍 自我介绍一般…

xadmin后台首页增加一个导入数据按钮

xadmin后台首页增加一个导入数据按钮 效果 流程 1、在添加小组件中添加一个html页面 2、写入html代码 3、在urls.py添加导入数据路由 4、在views.py中添加响应函数html代码 <!DOCTYPE html> <html lang

arcgis模版空库怎么用(一)

这里以某个项目的数据为例&#xff1a; 可以看到&#xff0c;属性表中全部只有列标题&#xff0c;无数据内容 可能有些人会认为空库是用来往里面加入信息的&#xff0c;其实不是&#xff0c;正确的用法如下&#xff1a; 一、下图是我演示用的数据&#xff0c;我们可以看到其中…

GJB系统设计说明模板

GJB系统设计说明模板及详解 1 范围 1.1 标识 1.2 系统概述 1.3 文档概述 2 引用文档 GJB XXX XXX XXX&#xff1b; XXX XXX。 前2章通用不再赘述 3 系统级设计决策 系统设计决策的目的:对系统规格说明中的关键需求(包括功能、质量属性和设计约束)进行分析,得到系统级概念性架构…

某小程序sign签名参数逆向分析

文章目录 1. 写在前面2. 接口分析3. 分析还原 【&#x1f3e0;作者主页】&#xff1a;吴秋霖 【&#x1f4bc;作者介绍】&#xff1a;擅长爬虫与JS加密逆向分析&#xff01;Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Python…

2000-2020年各省财政一般预算支出面板数据

2000-2020年各省财政一般预算支出面板数据 1、时间&#xff1a;2000-2020年 2、来源&#xff1a;国家统计局 3、指标&#xff1a;年份、省份、地方财政一般预算支出 4、范围&#xff1a;31省 指标解释&#xff1a;地方财政一般预算支出‌是指地方ZF根据预算安排&#xff0…

[羊城杯 2024]1z_misc

得到FL4G.zip和天机不可泄露.txt文件&#xff0c;其中压缩包需要解压密码&#xff1a; 二十八星宿&#xff1a; 东方苍龙七宿&#xff1a;角、亢、氐、房、心、尾、箕 南方朱雀七宿&#xff1a;鬼、井、柳、星、张、翼、轸 西方白虎七宿&#xff1a;奎、娄、胃、昴、毕、觜、…