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.pswp.cn/web/64899.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/64899.shtml
英文地址,請注明出處:http://en.pswp.cn/web/64899.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【SOC 芯片設計 DFT 學習專欄 -- 測試向量生成 ATPG (Automatic Test Pattern Generation) 】

文章目錄 OverviewATPG 的基本功能ATPG 的工作流程ATPG 應用場景示例示例 1&#xff1a;檢測單個信號的 Stuck-at Fault示例 2&#xff1a;針對 Transition Fault 的 ATPG ATPG 工具與常用工具鏈ATPG 優化與挑戰 Overview 本文主要介紹 DFT scan 中的 ATPG 功能。在 DFT (Desi…

2024 高通邊緣智能創新應用大賽智能邊緣計算賽道冠軍方案解讀

2024 高通邊緣智能創新應用大賽聚焦不同細分領域的邊緣智能創新應用落地&#xff0c;共設立三大熱門領域賽道——工業智能質檢賽道、智能邊緣計算賽道和智能機器人賽道。本文為智能邊緣計算賽道冠軍項目《端側大模型智能翻譯機》的開發思路與成果分享。 賽題要求 聚焦邊緣智能…

【Python運維】用Python和Ansible實現高效的自動化服務器配置管理

《Python OpenCV從菜鳥到高手》帶你進入圖像處理與計算機視覺的大門! 解鎖Python編程的無限可能:《奇妙的Python》帶你漫游代碼世界 隨著云計算和大規模數據中心的興起,自動化配置管理已經成為現代IT運維中不可或缺的一部分。通過自動化,企業可以大幅提高效率,降低人為錯…

微信小程序獲取后端數據

在小程序中獲取后端接口數據 通常可以使用 wx.request 方法&#xff0c;以下是一個基本示例&#xff1a; // pages/index/index.js Page({data: {// 用于存儲后端返回的數據resultData: [] },onLoad() {this.fetchData();},fetchData() {wx.request({url: https://your-backe…

應用架構模式-總體思路

采用引導式設計方法&#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…

微信小程序 覆蓋組件cover-view

wxml 覆蓋組件 <video src"../image/1.mp4" controls"{{false}}" event-model"bubble"> <cover-view class"controls"> <cover-view class"play" bind:tap"play"> <cover-image class"…

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…

力扣hot100——二叉樹

94. 二叉樹的中序遍歷 class Solution { public:vector<int> inorderTraversal(TreeNode* root) {vector<int> ans;stack<TreeNode*> stk;while (root || stk.size()) {while (root) {stk.push(root);root root->left;}auto cur stk.top();stk.pop();a…

設計模式 創建型 單例模式(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. 初始化網格的四個頂點…

mysql之組內排序ROW_NUMBER()函數

有個需求&#xff0c;需要組內排序&#xff0c;之前似乎從未接觸過此類排序&#xff0c;故查詢了一下&#xff0c;記錄sql執行結果。 表如下&#xff1a; play_log: 日期 (fdate)用戶 ID (user_id)歌曲 ID (song_id)2022-01-081000002022-01-161000002022-01-201000002022-0…

Android TV端彈出的PopupWindow沒有獲取焦點

在 TV 開發中&#xff0c;焦點管理是通過 Focus Navigation 實現的&#xff0c;PopupWindow 默認不接受焦點&#xff0c;導致遙控器無法選擇彈窗內的控件。這是因為 PopupWindow 默認不會將焦點傳遞到其內容視圖上。 要解決問題&#xff0c;可以通過以下步驟調整 PopupWindow …

活動預告 | Microsoft Power Platform 在線技術公開課:實現業務流程自動化

課程介紹 參加“Microsoft Power Platform 在線技術公開課&#xff1a;實現業務流程自動化”活動&#xff0c;了解如何更高效地開展業務。參加我們舉辦的本次免費培訓活動&#xff0c;了解如何借助 Microsoft AI Builder 和 Power Automate 優化工作流。結合使用這些工具可以幫…

FPGA(二)組成結構基礎內容

1. FPGA的基本結構 FPGA主要由以下部分組成&#xff1a; &#xff08;1&#xff09;可編程邏輯單元&#xff08;CLB&#xff09;&#xff1a;CLB是FPGA中最基本的邏輯單元&#xff0c;由查找表&#xff08;LUT&#xff09;和觸發器組成&#xff0c;可實現任意邏輯功能。查找表…