当前位置: 首页 > news >正文

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.xdnf.cn/news/197065.html

相关文章:

  • 阿里云ftp服务器登录要怎么做?如何访问ftp服务器?
  • 【权限模型】RBAC模型详解
  • 东莞SMT贴片加工工艺优化解析
  • 青年座谈会的读书汇报
  • Kotlin DSL 深度解析:从 Groovy 迁移的困惑与突破
  • vue3 如何设置全局属性
  • Docker的常用命令
  • WPF之Button控件详解
  • Crusader Kings III 王国风云 3(十字军之王 3) [DLC 解锁] [Steam] [Windows SteamOS macOS]
  • 多元函数微分之传统方法和全微分法
  • Qt笔记-自定义托盘弹出界面
  • 用于表格数据的神经网络分类器_TabPFN
  • Vuex持续保存数据 页面刷新不丢失 vuex-persistedstate
  • WPF 程序监控硬件设备状态变化的实现方案
  • vscode源代码管理Tab-文件右侧标志(M、A 等)的含义
  • await和async
  • (28)VTK C++开发示例 ---添加坐标轴
  • std::print 和 std::println
  • echarts自定义图表--仪表盘
  • 【机器学习】人工智能在电力电子领域的应用
  • 反射与注解实现动态功能扩展案例-插件系统
  • 模型上下文协议(MCP)深度解析:大模型从“思考者“进化为“行动者“
  • 总账主数据——Part 2 科目-4
  • 优先队列和单调队列(双端队列实现的)
  • stm32wb55rg (1) 基于IAR 创建stm32 工程模板
  • 序列密码算法ShanLooog512设计原理详解
  • DeepSearch复现篇:QwQ-32B ToolCall功能初探,以Agentic RAG为例
  • React速通笔记
  • 初识Python
  • 【Keil5-开发指南】