0、前序
上傳加密:客戶端上傳文件,后台加密,將加密后的文件存儲到文件服務器
下載解密:客戶端請求文件,后台從文件服務器獲取密文,解密返回客戶端
注:對文件服務器上存儲的文件需要做防篡改校驗
效果預覽:原文件,密文件,解密文件

1、客戶端(html)
<form action="http://192.168.2.170:8080/api/v1/test/file/encryption" method="post" enctype="multipart/form-data"> <p><input type="file" name="file"></p> <p><input type="text" name="clintMD5" value="e926b155ebf5f192bd71dbcec7dcb171"></p> <p><input type="submit" value="submit"></p> </form>
2、客戶端上傳、請求文件
3、服務端(源碼)
package com.huang.mydemo.encryption; import org.apache.commons.codec.digest.DigestUtils; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; @RestController @RequestMapping(value = "api/v1/test") public class FileUploadEncryptionController { //加密解密秘鑰,不能超過一個字節,也就是8位(生產環境可針對每個文件隨機生成秘鑰,確保每個文件的秘鑰都不一樣) private static final int secretKey = 99; //0x99 十六進制0-99,10進制0-255隨機產生【異或】秘鑰 private static int dataByte = 0; //文件字節內容 /** * 文件加密 * @param file 上傳的文件 * @param request * @return */ @PostMapping("file/encryption") public String encryption(@RequestParam("file") MultipartFile file, HttpServletRequest request) { try { //0、先檢查文件是否被篡改:此操作<選加> String srcMd5 = DigestUtils.md5Hex(file.getInputStream()); System.out.println("源文件MD5:"+srcMd5); String clintMD5 = request.getParameter("clintMD5"); System.out.println("clintMD5:"+clintMD5); if(!clintMD5.equals(srcMd5)) return "上傳文件被篡改"; //2、創建加密文件:臨時文件<異或加密:不改變文件大小和格式> File encFile = new File("F:\\Users\\admin\\Desktop\\enc_file.png"); if(!encFile.exists()){ encFile.createNewFile();//創建臨時文件 } //3、加密文件 InputStream fis = file.getInputStream(); OutputStream fos = new FileOutputStream(encFile); System.out.println("-------加密開始------"); while ((dataByte = fis.read()) > -1) { fos.write(dataByte^secretKey); } fis.close(); fos.flush(); fos.close(); System.out.println("-------加密完成------"); //4、生成加密文件的MD5,防止文件服務器篡改<必加> String encMd5 = DigestUtils.md5Hex(new FileInputStream(encFile)); System.out.println("密文件MD5:"+encMd5); //TODO 5、存儲加密文件 //TODO 6、刪除臨時文件:encFile return "ok"; } catch (Exception e) { return e.getMessage(); } } /** * 解密文件 * @param response */ @GetMapping("file/decryption") public void decryption(HttpServletResponse response) { File f = null; try { //TODO 1、從文件服務器獲取加密文件(這里直接取上面加密后的臨時文件,生產環境從oss或其他文件服務器獲取) File encFile = new File("F:\\Users\\admin\\Desktop\\enc_file.png"); //加密文件的MD5值,檢查文件是否被篡改 String encMd5 = DigestUtils.md5Hex(new FileInputStream(encFile)); System.out.println("密文件MD5:"+encMd5); //TODO 2、encMd5與存儲時的密碼MD5進行比對(略),檢查文件是否被篡改<必加> //3、創建解密文件:臨時文件 File decFile = new File("F:\\Users\\admin\\Desktop\\dec_file.jpeg"); if(!decFile.exists()){ decFile.createNewFile();//創建臨時文件 } //4、解密 InputStream fis = new FileInputStream(encFile); OutputStream fos = new FileOutputStream(decFile); System.out.println("--------------解密開始--------------"); while ((dataByte = fis.read()) > -1) { fos.write(dataByte^secretKey); } fis.close(); fos.close(); fos.flush(); System.out.println("--------------解密完成--------------"); //TODO 5、響應數據添加MD5,防止響應文件數據被篡改<選加> //6、返回解密后的文件 InputStream stream = new FileInputStream(decFile); ServletOutputStream out = response.getOutputStream(); byte buff[] = new byte[1024]; int length = 0; while ((length = stream.read(buff)) > 0) { out.write(buff,0,length); } stream.close(); out.close(); out.flush(); //TODO 7、刪除臨時文件:decFile } catch (Exception e) { e.printStackTrace(); } } }
4、思路(復盤)