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.mzph.cn/web/64899.shtml

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

相关文章

应用架构模式-总体思路

采用引导式设计方法&#xff1a;以企业级架构为指导&#xff0c;形成较为齐全的规范指引。在实践中总结重要设计形成决策要点&#xff0c;一个决策要点对应一个设计模式。自底向上总结采用该设计模式的必备条件&#xff0c;将之转化通过简单需求分析就能得到的业务特点&#xf…

【数据结构】双向循环链表的使用

双向循环链表的使用 1.双向循环链表节点设计2.初始化双向循环链表-->定义结构体变量 创建头节点&#xff08;1&#xff09;示例代码&#xff1a;&#xff08;2&#xff09;图示 3.双向循环链表节点头插&#xff08;1&#xff09;示例代码&#xff1a;&#xff08;2&#xff…

【Java设计模式-3】门面模式——简化复杂系统的魔法

在软件开发的世界里&#xff0c;我们常常会遇到复杂的系统&#xff0c;这些系统由多个子系统或模块组成&#xff0c;各个部分之间的交互错综复杂。如果直接让外部系统与这些复杂的子系统进行交互&#xff0c;不仅会让外部系统的代码变得复杂难懂&#xff0c;还会增加系统之间的…

Linux一些问题

修改YUM源 Centos7将yum源更换为国内源保姆级教程_centos使用中科大源-CSDN博客 直接安装包&#xff0c;走链接也行 Index of /7.9.2009/os/x86_64/Packages 直接复制里面的安装包链接&#xff0c;在命令行直接 yum install https://vault.centos.org/7.9.2009/os/x86_64/Pa…

HTML——57. type和name属性

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>type和name属性</title></head><body><!--1.input元素是最常用的表单控件--><!--2.input元素不仅可以在form标签内使用也可以在form标签外使用-…

uniapp本地加载腾讯X5浏览器内核插件

概述 TbsX5webviewUTS插件封装腾讯x5webview离线内核加载模块&#xff0c;可以把uniapp的浏览器内核直接替换成Android X5 Webview(腾讯TBS)最新内核&#xff0c;提高交互体验和流畅度。 功能说明 下载SDK插件 1.集成x5内核后哪些页面会由x5内核渲染&#xff1f; 所有plus…

设计模式 创建型 单例模式(Singleton Pattern)与 常见技术框架应用 解析

单例模式&#xff08;Singleton Pattern&#xff09;是一种创建型设计模式&#xff0c;旨在确保某个类在应用程序的生命周期内只有一个实例&#xff0c;并提供一个全局访问点来获取该实例。这种设计模式在需要控制资源访问、避免频繁创建和销毁对象的场景中尤为有用。 一、核心…

您的公司需要小型语言模型

当专用模型超越通用模型时 “越大越好”——这个原则在人工智能领域根深蒂固。每个月都有更大的模型诞生&#xff0c;参数越来越多。各家公司甚至为此建设价值100亿美元的AI数据中心。但这是唯一的方向吗&#xff1f; 在NeurIPS 2024大会上&#xff0c;OpenAI联合创始人伊利亚…

uniapp-vue3(下)

关联链接&#xff1a;uniapp-vue3&#xff08;上&#xff09; 文章目录 七、咸虾米壁纸项目实战7.1.咸虾米壁纸项目概述7.2.项目初始化公共目录和设计稿尺寸测量工具7.3.banner海报swiper轮播器7.4.使用swiper的纵向轮播做公告区域7.5.每日推荐滑动scroll-view布局7.6.组件具名…

使用 Python 实现随机中点位移法生成逼真的裂隙面

使用 Python 实现随机中点位移法生成逼真的裂隙面 一、随机中点位移法简介 1. 什么是随机中点位移法&#xff1f;2. 应用领域 二、 Python 代码实现 1. 导入必要的库2. 函数定义&#xff1a;随机中点位移法核心逻辑3. 设置随机数种子4. 初始化二维裂隙面5. 初始化网格的四个顶点…

活动预告 | Microsoft Power Platform 在线技术公开课:实现业务流程自动化

课程介绍 参加“Microsoft Power Platform 在线技术公开课&#xff1a;实现业务流程自动化”活动&#xff0c;了解如何更高效地开展业务。参加我们举办的本次免费培训活动&#xff0c;了解如何借助 Microsoft AI Builder 和 Power Automate 优化工作流。结合使用这些工具可以帮…

LLM(十二)| DeepSeek-V3 技术报告深度解读——开源模型的巅峰之作

近年来&#xff0c;大型语言模型&#xff08;LLMs&#xff09;的发展突飞猛进&#xff0c;逐步缩小了与通用人工智能&#xff08;AGI&#xff09;的差距。DeepSeek-AI 团队最新发布的 DeepSeek-V3&#xff0c;作为一款强大的混合专家模型&#xff08;Mixture-of-Experts, MoE&a…

el-pagination 为什么只能展示 10 条数据(element-ui@2.15.13)

好的&#xff0c;我来帮你分析前端为什么只能展示 10 条数据&#xff0c;以及如何解决这个问题。 问题分析&#xff1a; pageSize 的值&#xff1a; 你的 el-pagination 组件中&#xff0c;pageSize 的值被设置为 10&#xff1a;<el-pagination:current-page"current…

TCP网络编程(一)—— 服务器端模式和客户端模式

这篇文章将会编写基本的服务器网络程序&#xff0c;主要讲解服务器端和客户端代码的原理&#xff0c;至于网络名词很具体的概念&#xff0c;例如什么是TCP协议&#xff0c;不会过多涉及。 首先介绍一下TCP网络编程的两种模式&#xff1a;服务器端和客户端模式&#xff1a; 首先…

在K8S中,如何部署kubesphere?

在Kubernetes集群中&#xff0c;对于一些基础能力较弱的群体来说K8S控制面板操作存在一定的难度&#xff0c;此时kubesphere可以有效的解决这类难题。以下是部署kubesphere的操作步骤&#xff1a; 操作部署&#xff1a; 1. 部署nfs共享存储目录 yum -y install nfs-server e…

树莓派之旅-第一天 系统的烧录和设置

自言自语&#xff1a; 在此记录一下树莓派的玩法。以后有钱了买点来玩啊草 系统的安装烧录 系统下载 树莓派官网&#xff1a;https://www.raspberrypi.com/ 首页点击SoftWare进入OS下载页面 这里是安装工具&#xff1a;安装工具负责将系统镜像安装到sd卡中 点击下载符合自己…

商用车自动驾驶,迎来大规模量产「临界点」?

商用车自动驾驶&#xff0c;正迎来新的行业拐点。 今年初&#xff0c;交通部公开发布AEB系统运营车辆标配征求意见稿&#xff0c;首次将法规限制条件全面放开&#xff0c;有望推动商用车AEB全面标配&#xff0c;为开放场景的商用车智能驾驶市场加了一把火。 另外&#xff0c;…

人工智能及深度学习的一些题目

1、一个含有2个隐藏层的多层感知机&#xff08;MLP&#xff09;&#xff0c;神经元个数都为20&#xff0c;输入和输出节点分别由8和5个节点&#xff0c;这个网络有多少权重值&#xff1f; 答&#xff1a;在MLP中&#xff0c;权重是连接神经元的参数&#xff0c;每个连接都有一…

Solon 加入 GitCode:助力国产 Java 应用开发新飞跃

在当今数字化快速发展的时代&#xff0c;Java 应用开发框架不断演进&#xff0c;开发者们始终在寻找更快、更小、更简单的解决方案。近期&#xff0c;Solon 正式加入 GitCode&#xff0c;为广大 Java 开发者带来全新的开发体验&#xff0c;尤其是在国产应用开发进程中&#xff…

VScode 只能运行c,运行不了c++的解决问题

原文链接&#xff1a;Vscode只能运行c&#xff0c;运行不了c的解决方法 VScode 只能运行c&#xff0c;运行不了c&#xff0c;怎么回事呢&#xff0c;解决问题&#xff1a; 在tasks.json中加上“"-lstdc"”&#xff0c; 这样之后 要重启VScode&#xff0c;点击链接…