需求:工作遇到需要把.cer格式或.sm2格式的证书文件存放到数据库,用的时侯进行读取。
一、存储
1.上传证书到后台
在控制器获取到文件流先缓存一个临时文件到服务器,并返回临时文件的绝对路径
public ActionResult<String> uploadMerchantCert(@RequestParam("file") MultipartFile file, @RequestParam("fileType") Integer fileType) {
if (file.isEmpty()){
throw new ApplicationException(ErrorCodes.INVALID_ARGUMENTS,"请选择上传文件");
}
String fileName = file.getOriginalFilename();
if (fileType.equals(1) && !fileName.toLowerCase().endsWith(".cer")) {
throw new ApplicationException(ErrorCodes.INVALID_UPLOAD_FILE_TYPE, "文件类型错误");
} else if (fileType.equals(2) && !fileName.toLowerCase().endsWith(".sm2")) {
throw new ApplicationException(ErrorCodes.INVALID_UPLOAD_FILE_TYPE, "文件类型错误");
}
File tempFile = null;
String typeName = fileType.equals(1) ? "cer" : "sm2";
try {
tempFile = File.createTempFile("upload_tmp", "." + typeName);
} catch (IOException e) {
throw new ApplicationException(ErrorCodes.NOT_FOUND_FILE,"证书上传异常");
}
// 将上传文件内容写入临时文件
try (InputStream inputStream = file.getInputStream();
FileOutputStream fos = new FileOutputStream(tempFile)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
fos.write(buffer, 0, bytesRead);
}
}catch (Exception e){
throw new ApplicationException(ErrorCodes.NOT_FOUND_FILE,"证书上传异常");
}
// 返回临时文件的完整路径
return ActionResult.ok(tempFile.getAbsolutePath());
}
2.根据前端传输的临时文件路径获取到文件并存到数据库
public static void main(String[] args) {
Dto dto = new Dto();
Merchant merchant = new Merchant();
//存放证书
Path carPath = Paths.get(dto.getMerCerFilePath());//jdk1.8之后可以用File.toPath()
Path sm2Path = Paths.get(dto.getMerSm2FilePath());
merchant.setMerCer(getCertFile(carPath));
merchant.setMerSm2(getCertFile(sm2Path));
save(merchant); //这里做插入或更新数据库操作
//完成之后删除临时文件
delCertFile(carPath);
delCertFile(sm2Path);
}
/*********************************** private ***********************************/
/**
* 获取文件流
* @param filePath 文件路径
* @return 字节数组 对应实体类型为 private byte[] merCer; 数据库为blob类型
*/
private byte[] getCertFile(Path filePath) {
byte[] fileBytes;
try {
fileBytes = Files.readAllBytes(filePath);
} catch (IOException e) {
throw new ApplicationException("无法读取文件字节流");
}
return fileBytes;
}
/**
* 删除文件
* @param filePath 文件路径
*/
private void delCertFile(Path filePath) {
try {
Files.delete(filePath);
} catch (IOException e) {
log.error("删除临时文件异常:{}",e.getMessage());
}
}
3.注意实体属性类型(byte[])和数据库字段类型(blob)
1)实体属性类型
2)数据库字段类型
这样就可以把文件存入数据库~
二、读取和使用
1,查询数据库并根据文件流生成临时文件
public static void main(String[] args) {
Merchant merchant = merchantService.selectById(1);//查询对应渠道
//获取到数据
byte[] merCer = merchant.getMerCer();
byte[] merSm2 = merchant.getMerSm2();
TemFile cerTemFile = getTemFile(merCer, "cer");
TemFile sm2TemFile = getTemFile(merSm2, "sm2");
//使用
String cerPath = cerTemFile.getTemFilePath();
File cerFile = cerTemFile.getTemFile();
String sm2Path = sm2TemFile.getTemFilePath();
File sm2File = sm2TemFile.getTemFile();
//...
//使用完成之后删除临时文件
if (cerTemFile.getCerFile() != null){
cerTemFile.getCerFile().delete();
}
if (sm2TemFile.getSm2File() != null){
sm2TemFile.getSm2File().delete();
}
}
/**
*
* @param fileStream 从数据库读到的文件流
* @param typeName 文件格式的后缀 例:cer , sm2
* @return 返回对象对临时文件封装
*/
public TemFileDto getTemFile(byte[] fileStream, String typeName) {
TemFileDto temFileDto = new TemFileDto();
File cerFile = null;
try {
cerFile = File.createTempFile("tmp", "." + typeName);
} catch (IOException e) {
log.error("获取证书异常:{}",e.getMessage());
}
try(InputStream cerInputStream = new ByteArrayInputStream(fileStream);
FileOutputStream cerFileOutputStream = new FileOutputStream(cerFile);
) {
cerFile = File.createTempFile("tmp", ".cer");
byte[] target = fileStream;
int bytesRead;
while ((bytesRead = cerInputStream.read(target)) != -1) {
cerFileOutputStream.write(target, 0, bytesRead);
}
temFileDto.setTemFilePath(cerFile.getAbsolutePath());
temFileDto.setTemFile(cerFile);
} catch (IOException e) {
log.error("获取证书异常:{}",e.getMessage());
throw new ApplicationException(ErrorCodes.NOT_FOUND_FILE,"获取证书异常");
}
return temFileDto;
}
2.逻辑处理实体字段展示(Dto)
@Data
@ApiModel
public class TemFileDto {
@ApiModelProperty(value = "临时文件路径")
private String temFilePath;
@ApiModelProperty(value = "临时文件")
private File temFile;
}
到这里一整个的对于文件从存储到读取使用就已经结束啦~
欢迎留言,请多指教!