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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈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;可能添加迭代…