02_使用 AES 算法實現文件加密上傳至阿里云、解密下載

02_使用 AES 算法實現文件加密上傳至阿里云、解密下載

一、文件上傳下載接口 controller 層

@RestController
@RequestMapping("/api/common/file")
@Api(tags = "公共文件上傳")
@AllArgsConstructor
@Slf4j
public class FileV2Controller {private final OssUtil ossUtil;/*** 上傳單個加密文件并返回新文件名* @param file* @return*/@PostMapping("/uploadfile/encrypt")@ApiOperation("上傳單個加密文件")public CommonResult<String> fileUploadEncrypt(@RequestParam("file") MultipartFile file) {try {//獲取文件對應的字節數組byte[] originalBytes = file.getBytes();//這里是密鑰String secretKey = "1234567890123456"; // 記得換成你自己的密鑰//為文件生成一個新文件名 前面為UUID 后面為 文件后綴 (如原始文件名為 test.txt 加密后文件名 為 0x12.txt)String newFileName = UUID.randomUUID() + getFileSuffix(file.getOriginalFilename());//加密上傳 原始文件字節數組 新文件名 密鑰ossUtil.uploadEncryptedFile(originalBytes, newFileName, secretKey);//返回文件名return CommonResult.success(newFileName);} catch (Exception e) {log.error("加密上傳文件失敗", e);return CommonResult.failed("上傳失敗");}}/**** @param fileName* @return*/@GetMapping("/downloadfile/decrypt")@ApiOperation("下載單個加密文件")public ResponseEntity<byte[]> fileDownloadDecrypt(@RequestParam("fileName") String fileName) {try {//這里是密鑰String secretKey = "1234567890123456"; // 記得換成你自己的密鑰//解密下載 文件名 密鑰byte[] decryptedBytes = ossUtil.downloadDecryptedFile(fileName ,secretKey);// 設置響應頭部,通知瀏覽器下載文件HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);headers.setContentDisposition(ContentDisposition.attachment().filename(fileName).build());// 返回字節流,直接下載return new ResponseEntity<>(decryptedBytes, headers, HttpStatus.OK);} catch (Exception e) {log.error("解密下載文件失敗", e);return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);}}// 工具方法,提取后綴private String getFileSuffix(String filename) {return filename.substring(filename.lastIndexOf("."));}@GetMapping("/previewfile/decrypt")@ApiOperation("預覽單個加密文件")public ResponseEntity<byte[]> filePreviewDecrypt(@RequestParam("fileName") String fileName) {try {// 這里是密鑰 后續可以通過配置文件進行管理String secretKey = "1234567890123456"; // 記得換成你自己的密鑰// 解密下載 文件名 密鑰byte[] decryptedBytes = ossUtil.downloadDecryptedFile(fileName, secretKey);// 獲取文件類型(可根據實際情況調整)String fileExtension = getFileSuffix(fileName).toLowerCase();// 設置響應頭,根據文件類型進行調整HttpHeaders headers = new HttpHeaders();// 根據不同文件類型設置Content-Typeif (fileExtension.equals(".jpg") || fileExtension.equals(".jpeg") || fileExtension.equals(".png") || fileExtension.equals(".gif")) {// 圖片文件headers.setContentType(MediaType.IMAGE_JPEG); // 也可以根據具體類型選擇} else if (fileExtension.equals(".pdf")) {// PDF文件headers.setContentType(MediaType.APPLICATION_PDF);} else if (fileExtension.equals(".txt")) {// 文本文件headers.setContentType(MediaType.TEXT_PLAIN);} else {// 默認二進制流headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);}// 設置文件名,確保瀏覽器使用傳遞的文件名headers.setContentDisposition(ContentDisposition.inline().filename(fileName).build());// 返回字節流,直接預覽return new ResponseEntity<>(decryptedBytes, headers, HttpStatus.OK);} catch (Exception e) {log.error("解密預覽文件失敗", e);return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);}}
}

二、AESUtil 工具類

/*** AES加密解密工具類*/
public class AESUtil {// 定義使用的加密算法(這里是AES)private static final String ALGORITHM = "AES";/*** AES加密** @param data 原始數據(要加密的內容,比如文件內容的byte數組)* @param secretKey 密鑰(必須是16字節長度的字符串,比如 "1234567890abcdef")* @return 加密后的數據(byte數組)* @throws Exception 拋出任何加密異常*/public static byte[] encrypt(byte[] data, String secretKey) throws Exception {// 1. 創建一個AES專用的密鑰對象(把字符串密鑰變成加密用的key)SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(), ALGORITHM);// 2. 創建Cipher對象,指定用AES算法Cipher cipher = Cipher.getInstance(ALGORITHM);// 3. 初始化加密模式cipher.init(Cipher.ENCRYPT_MODE, keySpec);// 4. 執行加密操作,并返回加密后的數據return cipher.doFinal(data);}/*** AES解密** @param data 加密后的數據(byte數組)* @param secretKey 密鑰(加密和解密必須用同一個密鑰)* @return 解密后的原始數據(byte數組)* @throws Exception 拋出任何解密異常*/public static byte[] decrypt(byte[] data, String secretKey) throws Exception {// 1. 創建一個AES專用的密鑰對象SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(), ALGORITHM);// 2. 創建Cipher對象,指定用AES算法Cipher cipher = Cipher.getInstance(ALGORITHM);// 3. 初始化解密模式cipher.init(Cipher.DECRYPT_MODE, keySpec);// 4. 執行解密操作,并返回解密后的數據return cipher.doFinal(data);}
}

三、OSS 工具類

@Component
public class OssUtil {@Value("${aliyun.oss.endpoint}")private String endpoint;@Value("${aliyun.oss.accessKeyId}")private String accessKeyId;@Value("${aliyun.oss.accessKeySecret}")private String accessKeySecret;@Value("${aliyun.oss.bucketName}")private String bucketName;//文件存儲目錄private String filedir = "xxx/";// 上傳文件(指定文件名)private boolean uploadFile2OSS(InputStream instream, String fileName) {boolean success = false;try {// 創建上傳Object的MetadataObjectMetadata objectMetadata = new ObjectMetadata();objectMetadata.setContentLength(instream.available());objectMetadata.setCacheControl("no-cache");objectMetadata.setHeader("Pragma", "no-cache");objectMetadata.setContentDisposition("inline;filename=" + fileName);// 創建 OSSClient 實例OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);// 上傳文件PutObjectResult putResult = ossClient.putObject(bucketName, filedir + fileName, instream, objectMetadata);// 如果上傳沒有異常,設置 success 為 truesuccess = true;} catch (IOException e) {e.printStackTrace();} finally {try {if (instream != null) {instream.close();}} catch (IOException e) {e.printStackTrace();}}return success;}/*** 通過指定文件名從 OSS 下載文件* @param fileName 文件名* @return 文件的 InputStream*/public InputStream downloadFileFromOSS(String fileName) {InputStream inputStream = null;try {// 創建 OSSClient 對象OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);// 創建 GetObjectRequest 請求對象GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, filedir + fileName);// 獲取文件對象OSSObject ossObject = ossClient.getObject(getObjectRequest);// 獲取文件的 InputStreaminputStream = ossObject.getObjectContent();} catch (Exception e) {e.printStackTrace();}return inputStream;}/*** 上傳加密后的文件** @param bytes 文件原始內容(未加密)* @param fileName 要保存的文件名* @param secretKey 16位AES密鑰* @return 文件訪問地址*/public Boolean uploadEncryptedFile(byte[] bytes, String fileName, String secretKey) {try {// 1. 加密 生成原始文件內容加密后的 字節數組byte[] encryptedBytes = AESUtil.encrypt(bytes, secretKey);// 2. 生成流 通過加密后字節數組 轉為一個字節輸入流ByteArrayInputStream inputStream = new ByteArrayInputStream(encryptedBytes);// 3. 上傳 上傳到ossBoolean result = this.uploadFile2OSS(inputStream, fileName);return result;} catch (Exception e) {e.printStackTrace();return null;}}/*** 下載并解密文件** @param fileName 文件名* @param secretKey 16位AES密鑰* @return 解密后的原始字節數組*/public byte[] downloadDecryptedFile(String fileName, String secretKey) {try {// 1. 獲取文件輸入流(加密后的內容)InputStream encryptedInputStream = this.downloadFileFromOSS(fileName);if (encryptedInputStream == null) {return null;}// 2. 將輸入流轉為字節數組ByteArrayOutputStream baos = new ByteArrayOutputStream();byte[] buffer = new byte[4096];int bytesRead;while ((bytesRead = encryptedInputStream.read(buffer)) != -1) {baos.write(buffer, 0, bytesRead);}byte[] encryptedBytes = baos.toByteArray();// 3. 解密return AESUtil.decrypt(encryptedBytes, secretKey);} catch (Exception e) {e.printStackTrace();return null;}}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/81595.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/81595.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/81595.shtml

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

相關文章

力扣:24兩兩交換鏈表的節點

目錄 1.題目描述&#xff1a; 2.算法思路&#xff1a; 3.代碼展示&#xff1a; 1.題目描述&#xff1a; 給你一個鏈表&#xff0c;兩兩交換其中相鄰的節點&#xff0c;并返回交換后鏈表的頭節點。你必須在不修改節點內部的值的情況下完成本題&#xff08;即&#xff0c;只能…

smss源代碼分析之smss!SmpLoadSubSystemsForMuSession函數分析加載csrss.exe

第一部分&#xff1a; Next SmpSubSystemsToLoad.Flink; while ( Next ! &SmpSubSystemsToLoad ) { p CONTAINING_RECORD( Next, SMP_REGISTRY_VALUE, Entry )…

MIT6.S081-lab8前置

MIT6.S081-lab8前置 注&#xff1a;本部分除了文件系統還包含了調度的內容。 調度 調度涉及到保存寄存器&#xff0c;恢復寄存器&#xff0c;就這一點而言&#xff0c;和我們的 trap 很像&#xff0c;但是實際上&#xff0c;我們實現并不是復用了 trap 的邏輯&#xff0c;我…

哈希函數詳解(SHA-2系列、SHA-3系列、SM3國密)案例:構建簡單的區塊鏈——密碼學基礎

文章目錄 一、密碼哈希函數概述1.1 哈希函數的基本概念1.2 哈希函數在數據安全中的應用 二、SHA-2系列算法詳解2.1 SHA-2的起源與發展2.2 SHA-256技術細節與實現2.3 SHA-384和SHA-512的特點2.4 SHA-2系列算法的安全性評估 三、SHA-3系列算法詳解3.1 SHA-3的起源與設計理念3.2 K…

待驗證---Oracle 19c 在 CentOS 7 上的快速安裝部署指南

Oracle 19c 在 CentOS 7 上的快速安裝部署指南 Oracle Database 19c 是一個功能強大的企業級數據庫系統&#xff0c;下面我將為您提供在 CentOS 7 上快速安裝部署 Oracle 19c 的詳細步驟。 一、準備工作 1. 系統要求 CentOS 7 (64位)最小內存: 2GB (推薦 8GB 以上)最小磁盤…

stm32 HAI庫 SPI(一)原理

基本特點 通信方式&#xff1a;同步、串行&#xff08;串行、并行、并發&#xff0c;別再傻傻分不清了&#xff01;_串行和并行的區別-CSDN博客&#xff09;、全雙工 &#xff08;也可以選擇半雙工&#xff09;速率&#xff1a;50MHZ以下數據格式&#xff1a;8位/16位傳輸順序…

OpenResty技術深度解析:原理、應用與生態對比-優雅草卓伊凡

OpenResty技術深度解析:原理、應用與生態對比-優雅草卓伊凡 一、OpenResty技術概述 1.1 OpenResty是什么? OpenResty是一個基于Nginx的高性能Web平臺,它將標準的Nginx核心與一系列強大的第三方模塊(主要是LuaJIT)捆綁在一起,形成了一個全功能的Web應用服務器。不同于傳…

二維碼批量識別—混亂多張二維碼識別-物品分揀—-未來之窗-仙盟創夢IDE

仙盟模型 用途 精準分揀&#xff1a;快速準確識別物品上復雜或多個二維碼&#xff0c;依據碼中信息&#xff08;如目的地、品類等&#xff09;實現物品自動化分揀&#xff0c;提高分揀效率與準確性。庫存管理&#xff1a;識別入庫、出庫物品二維碼&#xff0c;更新庫存數據&am…

scikit-learn在監督學習算法的應用

shiyonguyu大家好&#xff0c;我是我不是小upper&#xff01;最近行業大環境不是很好&#xff0c;有人苦惱別人都開始著手項目實戰了&#xff0c;自己卻還卡在 scikit-learn 的代碼語法上&#xff0c;連簡單的示例運行起來都磕磕絆絆。確實&#xff0c;對很多機器學習初學者來說…

dragonfly docker pull 報錯 error parsing HTTP 404 response body

問題描述 在部署了 dragonfly 的機器上 docker pull 鏡像發現如下報錯 docker pull uhub.service.ucloud.cn/openbayes/test-job-sidecar:latest Error response from daemon: error parsing HTTP 404 response body: invalid character p after top-level value: "404 …

C++11新特性_標準庫_正則表達式庫

C11 引入了標準正則表達式庫 <regex>&#xff0c;它提供了強大且靈活的文本匹配和替換功能。下面為你詳細介紹該庫的相關內容&#xff0c;包括主要組件、使用方法、示例代碼等。 主要組件 std::regex&#xff1a;用于表示一個正則表達式對象&#xff0c;可通過構造函數…

【多線程】七、POSIX信號量 環形隊列的生產者消費者模型

文章目錄 Ⅰ. 信號量一、POSIX 信號量的概念二、POSIX 信號量的類型區別三、POSIX 信號量與 SystemV 信號量的區別Ⅱ. 線程信號量基本原理一、為什么要引入信號量?二、PV 操作三、POSIX 信號量的實現原理四、CAS操作介紹Ⅲ. POSIX未命名信號量接口一、初始化無名信號量二、銷毀…

ES基本使用方式

ES基本使用 文章目錄 ES基本使用1.es的訪問使用URL訪問 2.mapping的理解Dynamic Mappingkeyword 與 text的區別?基礎定義與核心差異主字段&#xff0c;子字段 創建mapping 3.創建索引4.查看索引列表5.刪除索引6.添加數據7.查詢數據 重置es密碼&#xff0c;初始用戶elastic el…

玩轉Docker | 使用Docker部署AI證件照工具

玩轉Docker | 使用Docker部署AI證件照工具 前言一、HivisionIDPhotos介紹項目簡介主要特點二、系統要求環境要求環境檢查Docker版本檢查檢查操作系統版本三、部署HivisionIDPhotos服務下載鏡像創建容器創建容器檢查容器狀態檢查服務端口安全設置四、訪問HivisionIDPhotos服務訪…

【掌握 DDL】:SQL 中的數據庫與表管理

掌握 DDL&#xff1a;SQL 中的數據庫與表管理 掌握 DDL&#xff1a;SQL 中的數據庫與表管理數據庫 DDL創建數據庫查看數據庫查看所有數據庫查看數據庫創建語句 進入數據庫刪除數據庫備份數據庫備份恢復 查看數據庫連接深入理解數據庫創建與刪除數據庫字符集與校驗規則 表 DLL創…

基于「騎手外賣系統」串聯7大設計原則

你說得對&#xff01;這些設計原則聽起來都很抽象、很“玄”&#xff0c;如果不是實際開發過系統&#xff0c;很難理解“到底為什么要這樣設計”。 那我現在就用一個你能想象得很清楚的真實例子&#xff0c;幫你把這7個設計原則一一落地到具體情境里&#xff0c;你會一眼明白。…

基于輕量化YOLO的車載設備實時視頻目標檢測方案

一、背景與需求 在智能汽車后裝市場,設備的視覺感知能力日益成為差異化競爭點。傳統后裝產品主要關注車輛診斷和位置跟蹤,但在智能輔助駕駛(ADAS)與車聯網(V2X)大潮下,如果能在已有硬件平臺上新增“視頻級行人、車輛、交通標志檢測”功能,不僅可提升安全預警,也能為后…

HTTPS協議:更安全的HTTP

目錄 1. 前言 2. HTTP 與 HTTPS&#xff1a;安全的分水嶺 2.1 HTTP 的安全隱患 2.2 HTTPS 的安全提升 3. HTTPS 的核心概念 3.1 加密三劍客&#xff1a;對稱加密、非對稱加密與哈希算法 3.2 SSL/TLS 握手過程&#xff1a;建立安全通道的關鍵步驟 3.3 數字證書&#xff…

使用 Go 和 Gorgonia 實現圖像驗證碼識別系統

本文將介紹如何使用 Go 語言結合 Gorgonia 構建一個簡單的圖像驗證碼識別模型。Gorgonia 是一個專為機器學習打造的計算圖庫&#xff0c;在 Go 中支持自動微分與深度學習構建。 1. 項目依賴 首先安裝 Go 語言環境和 Gorgonia&#xff1a; 登錄后復制 go install gorgonia.org/g…

list的兩種設計

1. 內存布局對比 (1) MSVC 的實現 cpp class _List_node {_List_node* _Next; // 指向下一個節點_List_node* _Prev; // 指向前一個節點_Value_type _Value; // 存儲的數據 }; 特點&#xff1a; 每個節點包含兩個指針和一個數據成員。 Debug 模式&#xff1a;可能添加迭代…