为了在上传文件时增加加密处理,并从Spring Boot项目的配置文件中读取加密密钥,你需要进行以下几个步骤的修改:
1.添加加密依赖:确保你的项目中已经包含了用于加密解密的库,如javax.crypto(Java自带)或其他第三方加密库,如Bouncy Castle。
2.配置加密密钥:在Spring Boot的application.yml或application.properties文件中,添加加密密钥的配置项。
# application.yml
encrypt:
key: your-encryption-key-here
或者
# application.properties
encrypt.key=your-encryption-key-here
3.读取配置中的密钥:使用@Value注解从配置中读取加密密钥。
4.实现加密逻辑:在上传文件之前,使用读取到的密钥对文件内容进行加密。
代码案例:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.util.Base64;
@Service
public class SysFileInfoServiceImpl extends ServiceImpl<SysFileInfoMapper, SysFileInfo> implements SysFileInfoService {
private static final Log log = Log.get();
@Resource
private FileOperator fileOperator;
private String currentSavePath = "";
// 使用@Value注解注入配置文件中的加密密钥
@Value("${encrypt.key}")
private String encryptionKey;
@Override
public void uploadFile(MultipartFile file) {
// 生成文件的唯一id
Long fileId = IdWorker.getId();
// 获取文件原始名称
String originalFilename = file.getOriginalFilename();
// 获取文件后缀
String fileSuffix = null;
if (ObjectUtil.isNotEmpty(originalFilename)) {
fileSuffix = StrUtil.subAfter(originalFilename, SymbolConstant.PERIOD, true);
}
// 生成文件的最终名称
String finalName = fileId + SymbolConstant.PERIOD + fileSuffix;
// 存储文件
byte[] bytes;
try {
if(encryption != null && encryption.intValue() == 1){
// 加密文件内容
bytes = encryptFileContent(file, encryptionKey);
}else{
//不加密
bytes = file.getBytes();
}
fileOperator.storageFile(FileConfig.DEFAULT_BUCKET, finalName, bytes);
} catch (IOException e) {
throw new ServiceException(SysFileInfoExceptionEnum.ERROR_FILE);
}
}
/**
* 加密文件内容
* @param file 原始文件
* @param key 密钥
* @return 加密后的字节流
*/
private byte[] encryptFileContent(MultipartFile file, String key) {
try {
// 创建密钥
Key secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
// 初始化Cipher
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
// 读取文件内容并加密
byte[] fileContent = file.getBytes();
byte[] encryptedContent = cipher.doFinal(fileContent);
// 返回加密后的字节流
return encryptedContent;
} catch (Exception e) {
log.error("Encryption failed.", e);
throw new ServiceException(SysFileInfoExceptionEnum.ERROR_ENCRYPTION);
}
}
}
下载接口:
public void download(SysFileInfoParam sysFileInfoParam, HttpServletResponse response) {
// 获取文件信息结果集
SysFileInfoResult sysFileInfoResult = this.getFileInfoResult(sysFileInfoParam.getId());
String fileName = sysFileInfoResult.getFileOriginName();
byte[] fileBytes = null;
if(sysFileInfoResult.getIsEncryption() != null && sysFileInfoResult.getIsEncryption().intValue() == 1){
//解密
try {
fileBytes = decryptFileContent(sysFileInfoResult.getFileBytes(), encryptionKey);
} catch (Exception e) {
log.error("文件解密失败={}",e);
throw new ServiceException(SysFileInfoExceptionEnum.ERROR_DECRYPT);
}
}else {
//不解密
fileBytes = sysFileInfoResult.getFileBytes();
}
DownloadUtil.download(fileName, fileBytes, response);
}
//解密方法
/**
* 解密文件内容
* @param encryptedContent 加密后的文件内容
* @param key 解密密钥
* @return 解密后的字节流
* @throws Exception 加密/解密过程中可能抛出的异常
*/
private byte[] decryptFileContent(byte[] encryptedContent, String key) throws Exception {
Key secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
// 执行解密操作
byte[] decryptedContent = cipher.doFinal(encryptedContent);
return decryptedContent;
}
DownloadUtil工具类:
public class DownloadUtil {
private static final Log log = Log.get();
public static void download(String fileName, byte[] fileBytes, HttpServletResponse response) {
try {
response.reset();
response.setHeader("Content-Disposition", "attachment; filename=\"" + URLUtil.encode(fileName) + "\"");
response.addHeader("Content-Length", "" + fileBytes.length);
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
response.setContentType("application/octet-stream;charset=UTF-8");
IoUtil.write(response.getOutputStream(), true, fileBytes);
} catch (IOException e) {
log.error(">>> 下载文件异常,请求号为:{},具体信息为:{}", RequestNoContext.get(), e.getMessage());
throw new ServiceException(SysFileInfoExceptionEnum.DOWNLOAD_FILE_ERROR);
}
}
/**
* 下载文件
*
* @param file 要下载的文件
* @param response 响应
* @author xuyuxiang
* @date 2020/8/5 21:46
*/
public static void download(File file, HttpServletResponse response) {
// 获取文件字节
byte[] fileBytes = FileUtil.readBytes(file);
//获取文件名称
String fileName;
try {
fileName = URLEncoder.encode(file.getName(), CharsetUtil.UTF_8);
} catch (UnsupportedEncodingException e) {
log.error(">>> 下载文件异常,请求号为:{},具体信息为:{}", RequestNoContext.get(), e.getMessage());
throw new ServiceException(SysFileInfoExceptionEnum.DOWNLOAD_FILE_ERROR);
}
//下载文件
download(fileName, fileBytes, response);
}
/**
* 将url的文件下载到目标文件
*
* @param url 下载url
* @param file 目标文件
* @author xuyuxiang
* @date 2021/3/25 16:51
*/
public static void downloadToFile(String url, File file) {
if (url == null || url.isEmpty()) throw new ServiceException(SysFileInfoExceptionEnum.DOWNLOAD_FILE_ERROR);
if (file == null) throw new ServiceException(SysFileInfoExceptionEnum.NOT_EXISTED_FILE);
try {
URL uri = new URL(url);
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) uri.openConnection();
InputStream stream = connection.getInputStream();
if (stream == null) {
throw new ServiceException(SysFileInfoExceptionEnum.FILE_STREAM_ERROR);
}
FileUtil.writeFromStream(stream, file);
connection.disconnect();
} catch (Exception e) {
log.error(">>> 下载文件异常,请求号为:{},具体信息为:{}", RequestNoContext.get(), e.getMessage());
throw new ServiceException(SysFileInfoExceptionEnum.DOWNLOAD_FILE_ERROR);
}
}
}