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;

    @Autowired
    S3Config s3Config;


    @PostConstruct
    public 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("."));
            //取出同名文件的最大number
            int 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, 设置为空表示列出所有的object
        objectsRequest.setDelimiter(deleteAll ? "" : "/");
        // 设置最大遍历出多少个对象, 一次listobject最大支持1000
        objectsRequest.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();
            // 清空response
            response.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.com
    accessKey: xxxxx
    secretKey: xxxx
    bucketName: xxx
    region: cn-north-1
    project: xxx
    module: dev

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

STM32单片机芯片与内部57 SPI 数据手册 寄存器

目录 一、SPI寄存器 1、SPI控制寄存器 1(SPI_CR1)(I2S模式下不使用) 2、SPI控制寄存器 2(SPI_CR2) 3、SPI 状态寄存器(SPI_SR) 4、SPI 数据寄存器(SPI_DR) 5、SPI CRC多项式寄存器(SPI_CRCPR)(I2S模式下不使用&#xff09; 6、SPI Rx CRC寄存器(SPI_RXCRCR)(I2S模式下不…

QT-------------自定义插件和库

以下是一个使用 Qt 实现图表交互操作的示例&#xff0c;涵盖了自定义图表视图类、不同类型的柱状图和饼图等内容。 实现思路 自定义图表视图类&#xff1a;创建一个从 QChartView 派生的自定义类&#xff0c;用于处理图表的交互操作。主窗口设计初始化&#xff1a;在主窗口中…

【Python】闭包

闭包&#xff08;Closure&#xff09;是指一个函数记住了并可以访问它的词法作用域&#xff08;lexical scope&#xff09;&#xff0c;即使这个函数在词法作用域之外执行。 闭包其实就是延伸了作用域的函数&#xff0c;包括被延伸函数主体中引用的非全局变量和局部变量。这些…

矩阵运算提速——玩转opencv::Mat

介绍:用Eigen或opencv::Mat进行矩阵的运算&#xff0c;比用cpp的vector或vector进行矩阵运算要快吗? 使用 Eigen 或 OpenCV 的 cv::Mat 进行矩阵运算通常比使用 std::vector<int> 或 std::vector<double> 更快。这主要有以下几个原因&#xff1a; 优化的底层实现…

FastDeploy部署paddlecls分类模型(windows)

目录 写在前面 总体步骤 C SDK编译库 方式1&#xff1a;编译安装 方式2&#xff1a;下载预编译库 准备模型、文件、代码和数据 模型文件类型 samples代码 待预测图像 使用 FastDeploy C SDK 将cpp源码编译为exe 编写cpp代码 cpp代码编译exe 运行可执行程序exe 将…

【第二部分--Python之基础】03 容器类型的数据

Python内置的数据类型如序列&#xff08;列表、元组等&#xff09;、集合和字典等可以容纳多项数据&#xff0c;我们称它们为容器类型的数据。 序列 序列&#xff08;sequence&#xff09;是一种可迭代的、元素有序的容器类型的数据。 序列包括列表&#xff08;list&#xff…

linux shell脚本 【分支结构case...in 、循环结构、函数】内附练习

1.思维导图 2.练习 1.定义一个find函数&#xff0c;查找ubuntu和root的gid 2.定义一个数组&#xff0c;写一个函数完成对数组的冒泡排序 bubble() {n${#arr[*]}for((i0;i<n-1;i));dofor((j0;j<n-1-i;j));doif ((arr[j]>arr[j1]));thentemp${arr[j]}arr[j]${arr[j1]}a…

基于SpringBoot和OAuth2,实现通过Github授权登录应用

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

从单点 Redis 到 1 主 2 从 3 哨兵的架构演进之路

一、前言 我们有个项目中用的 MySQL、Redis、ES、微服务都是单节点部署的&#xff0c;没有做集群模式部署&#xff0c;为了提高整体的可用性&#xff0c;对项目的部署架构进行了升级&#xff0c;支持高可用。 二、部署拓扑图 我们项目的测试环境 12 台服务器已经部署好了&am…

SQL 中的 EXISTS

我们先从 SQL 中最基础的 WHERE 子句开始。 比如下面这条 SQL 语句&#xff1a; 很显然&#xff0c;在执行这条 SQL 语句的时候&#xff0c;DBMS 会扫描 Student 表中的每一条记录&#xff0c;然后把符合 Sdept IS 这个条件的所有记录筛选出来&#xff0c;并放到结果集里面去…

大型概念模型:在句子表示空间中的语言建模

《Large Concept Models: Language Modeling in a Sentence Representation Space》这篇论文介绍了一种新的语言模型方法&#xff0c;它在句子表示空间中进行建模。该方法旨在改进传统语言模型的局限性&#xff0c;通过捕捉更高级别的语义信息来提高自然语言处理任务的表现。 模…

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

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

YK人工智能(三)——万字长文学会torch深度学习

2.1 张量 本节主要内容&#xff1a; 张量的简介PyTorch如何创建张量PyTorch中张量的操作PyTorch中张量的广播机制 2.1.1 简介 几何代数中定义的张量是基于向量和矩阵的推广&#xff0c;比如我们可以将标量视为零阶张量&#xff0c;矢量可以视为一阶张量&#xff0c;矩阵就是…

企业二要素如何用C#实现

一、什么是企业二要素&#xff1f; 企业二要素&#xff0c;通过输入统一社会信用代码、企业名称或统一社会信用代码、法人名称&#xff0c;验证两者是否匹配一致。 二、企业二要素适用哪些场景&#xff1f; 例如&#xff1a;信用与金融领域 1.信用评级&#xff1a;信用评级…

Visual Studio 2022安装教程

1、下载网址 Visual Studio 2022 IDE安装网址借助 Visual Studio 设计&#xff0c;具有自动完成、构建、调试、测试功能的代码将与 Git 管理和云部署融为一体。https://visualstudio.microsoft.com/zh-hans/vs/ 点击图片所示 双击运行 2、安装 点击C桌面开发&#xff08;右边…

TVS二极管选型【EMC】

TVS器件并联在电路中&#xff0c;当电路正常工作时&#xff0c;他处于截止状态&#xff08;高阻态&#xff09;&#xff0c;不影响线路正常工作&#xff0c;当线路处于异常过压并达到其击穿电压时&#xff0c;他迅速由高阻态变为低阻态&#xff0c;给瞬间电流提供一个低阻抗导通…

redis的集群模式与ELK基础

一、redis的集群模式 1.主从复制 &#xff08;1&#xff09;概述 主从模式&#xff1a;这是redis高可用的基础&#xff0c;哨兵和集群都是建立在此基础之上。 主从模式和数据库的主从模式是一样的&#xff0c;主负责写入&#xff0c;然后把写入的数据同步到从服务器&#xff…

Kubernetes第三天

1.pod容器的三种重启策略 查看容器的重启策略有哪些 kubectl explain po.spec. 发现有Always OnFailure Never Always,当容器退出时&#xff0c;始终重启容器 OnFailure,当容器正常退出时&#xff0c;不会自动重启容器&#xff0c;当容器异常退出时&#xff0c;重启容器 …

61.旋转链表 python

旋转链表 题目题目描述示例 1&#xff1a;示例 2&#xff1a;提示&#xff1a; 题解思路分析Python 实现代码代码解释提交结果 题目 题目描述 给你一个链表的头节点 head &#xff0c;旋转链表&#xff0c;将链表每个节点向右移动 k 个位置。 示例 1&#xff1a; 输入&#…

什么时候出现对象?芊芊测字,ai测字

芊芊测字地址&#xff1a;芊芊测字-ai免费测字