文件校验

This commit is contained in:
xy
2024-08-14 21:07:27 +08:00
parent a0142917c7
commit adbb9a16f4
3 changed files with 80 additions and 14 deletions

View File

@@ -30,4 +30,8 @@ public class UploadFileDto {
@ApiModelProperty("文件包数据") @ApiModelProperty("文件包数据")
private String data; private String data;
@SerializedName("FileCheck")
@ApiModelProperty("文件校验码")
private String fileCheck;
} }

View File

@@ -17,6 +17,7 @@ import com.njcn.access.pojo.dto.devModel.*;
import com.njcn.access.pojo.dto.file.FileRedisDto; import com.njcn.access.pojo.dto.file.FileRedisDto;
import com.njcn.access.pojo.po.CsLineModel; import com.njcn.access.pojo.po.CsLineModel;
import com.njcn.access.service.*; import com.njcn.access.service.*;
import com.njcn.access.utils.CRC32Utils;
import com.njcn.access.utils.JsonUtil; import com.njcn.access.utils.JsonUtil;
import com.njcn.common.pojo.dto.DeviceLogDTO; import com.njcn.common.pojo.dto.DeviceLogDTO;
import com.njcn.common.pojo.exception.BusinessException; import com.njcn.common.pojo.exception.BusinessException;
@@ -37,6 +38,7 @@ import com.njcn.system.pojo.vo.DictTreeVO;
import com.njcn.web.utils.RequestUtil; import com.njcn.web.utils.RequestUtil;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.util.encoders.Hex;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
@@ -152,10 +154,19 @@ public class CsDevModelServiceImpl implements ICsDevModelService {
} }
} }
public static void main(String[] args) {
}
@Override @Override
public void uploadDevFile(MultipartFile file,String id,String path) { public void uploadDevFile(MultipartFile file,String id,String path) {
DeviceLogDTO logDto = null; DeviceLogDTO logDto = null;
try { try {
byte[] bytes = file.getBytes();
int length = bytes.length;
//生成文件校验码
int crc = CRC32Utils.calculateCRC32(bytes,length,0xffffffff);
String hexString = String.format("%08X", crc);
//判断nDid是否存在 //判断nDid是否存在
CsEquipmentDeliveryVO csEquipmentDeliveryVO = csEquipmentDeliveryService.queryEquipmentBynDid(id); CsEquipmentDeliveryVO csEquipmentDeliveryVO = csEquipmentDeliveryService.queryEquipmentBynDid(id);
logDto = new DeviceLogDTO(); logDto = new DeviceLogDTO();
@@ -172,61 +183,59 @@ public class CsDevModelServiceImpl implements ICsDevModelService {
//获取版本 //获取版本
String version = csTopicService.getVersion(id); String version = csTopicService.getVersion(id);
int cap = 50 * 1024; int cap = 50 * 1024;
byte[] bytes = file.getBytes();
int length = bytes.length;
//需要分片处理 一帧按50k大小传递 //需要分片处理 一帧按50k大小传递
if (length > cap){ if (length > cap){
//需要循环的次数 //需要循环的次数
int times = bytes.length / cap + 1; int times = bytes.length / cap + 1;
for (int i = 1; i <= times; i++) { for (int i = 1; i <= times; i++) {
FileRedisDto fileRedisDto = (FileRedisDto) redisUtil.getObjectByKey("uploadFileStep");
byte[] lsBytes; byte[] lsBytes;
if (length > 50*1024) { if (length > 50*1024) {
lsBytes = Arrays.copyOfRange(bytes, (i - 1) * cap, i * cap); lsBytes = Arrays.copyOfRange(bytes, (i - 1) * cap, i * cap);
ReqAndResDto.Req req = getPojo(i,path,file,bytes.length,lsBytes,(i-1)*cap); ReqAndResDto.Req req = getPojo(i,path,file,bytes.length,lsBytes,(i-1)*cap,hexString);
publisher.send("/Pfm/DevFileCmd/" + version + "/" + id, new Gson().toJson(req), 1, false); publisher.send("/Pfm/DevFileCmd/" + version + "/" + id, new Gson().toJson(req), 1, false);
logDto.setOperate(id + "设备上送文件,这是第" + i + ""); logDto.setOperate(id + "设备上送文件,这是第" + i + "");
logDto.setResult(1); logDto.setResult(1);
length = length - cap; length = length - cap;
//判断是否重发 //判断是否重发
sendNextStep(logDto,path,file,bytes.length,lsBytes,(i-1)*cap,version,id,i); sendNextStep(logDto,path,file,bytes.length,lsBytes,(i-1)*cap,version,id,i,hexString);
FileRedisDto fileRedisDto = (FileRedisDto) redisUtil.getObjectByKey("uploadFileStep");
//重发之后判断继续循环还是跳出循环 //重发之后判断继续循环还是跳出循环
if (!Objects.equals(fileRedisDto.getCode(),200)) { if (!Objects.equals(fileRedisDto.getCode(),200)) {
break; break;
} }
} else { } else {
lsBytes = Arrays.copyOfRange(bytes, (i - 1) * cap, bytes.length); lsBytes = Arrays.copyOfRange(bytes, (i - 1) * cap, bytes.length);
ReqAndResDto.Req req = getPojo(i,path,file,bytes.length,lsBytes,(i-1)*cap); ReqAndResDto.Req req = getPojo(i,path,file,bytes.length,lsBytes,(i-1)*cap,hexString);
publisher.send("/Pfm/DevFileCmd/" + version + "/" + id, new Gson().toJson(req), 1, false); publisher.send("/Pfm/DevFileCmd/" + version + "/" + id, new Gson().toJson(req), 1, false);
logDto.setOperate(id + "设备上送文件,这是最后一帧,为第" + i + ""); logDto.setOperate(id + "设备上送文件,这是最后一帧,为第" + i + "");
logDto.setResult(1); logDto.setResult(1);
//判断是否重发 //判断是否重发
sendNextStep(logDto,path,file,bytes.length,lsBytes,(i-1)*cap,version,id,i); sendNextStep(logDto,path,file,bytes.length,lsBytes,(i-1)*cap,version,id,i,hexString);
} }
csLogsFeignClient.addUserLog(logDto); csLogsFeignClient.addUserLog(logDto);
} }
} else { } else {
ReqAndResDto.Req req = getPojo(1,path,file,length,bytes,0); ReqAndResDto.Req req = getPojo(1,path,file,length,bytes,0,hexString);
publisher.send("/Pfm/DevFileCmd/" + version + "/" + id, new Gson().toJson(req), 1, false); publisher.send("/Pfm/DevFileCmd/" + version + "/" + id, new Gson().toJson(req), 1, false);
logDto.setOperate(id + "系统上送文件,当前文件只有1帧"); logDto.setOperate(id + "系统上送文件,当前文件只有1帧");
logDto.setResult(1); logDto.setResult(1);
csLogsFeignClient.addUserLog(logDto); csLogsFeignClient.addUserLog(logDto);
//判断是否重发 //判断是否重发
sendNextStep(logDto,path,file,length,bytes,0,version,id,1); sendNextStep(logDto,path,file,length,bytes,0,version,id,1,hexString);
} }
} catch (Exception e) { } catch (Exception e) {
assert logDto != null; assert logDto != null;
logDto.setResult(0); logDto.setResult(0);
logDto.setFailReason(AccessResponseEnum.UPLOAD_ERROR.getMessage()); logDto.setFailReason(AccessResponseEnum.UPLOAD_ERROR.getMessage());
csLogsFeignClient.addUserLog(logDto); csLogsFeignClient.addUserLog(logDto);
throw new RuntimeException(e); throw new BusinessException(AccessResponseEnum.UPLOAD_ERROR);
} }
} }
/** /**
* 上送文件至装置 * 上送文件至装置
*/ */
public ReqAndResDto.Req getPojo(Integer mid, String path, MultipartFile file, Integer allLength, byte[] bytes, Integer offset) { public ReqAndResDto.Req getPojo(Integer mid, String path, MultipartFile file, Integer allLength, byte[] bytes, Integer offset, String fileCheck) {
//组装报文 //组装报文
ReqAndResDto.Req reqAndResParam = new ReqAndResDto.Req(); ReqAndResDto.Req reqAndResParam = new ReqAndResDto.Req();
reqAndResParam.setMid(mid); reqAndResParam.setMid(mid);
@@ -240,6 +249,7 @@ public class CsDevModelServiceImpl implements ICsDevModelService {
uploadFileDto.setOffset(offset); uploadFileDto.setOffset(offset);
uploadFileDto.setLen(bytes.length); uploadFileDto.setLen(bytes.length);
uploadFileDto.setData(Base64.getEncoder().encodeToString(bytes)); uploadFileDto.setData(Base64.getEncoder().encodeToString(bytes));
uploadFileDto.setFileCheck(fileCheck);
reqAndResParam.setMsg(uploadFileDto); reqAndResParam.setMsg(uploadFileDto);
return reqAndResParam; return reqAndResParam;
} }
@@ -247,17 +257,17 @@ public class CsDevModelServiceImpl implements ICsDevModelService {
/** /**
* 根据装置响应来判断发送的内容 * 根据装置响应来判断发送的内容
*/ */
public void sendNextStep(DeviceLogDTO logDto, String path, MultipartFile file, int length, byte[] bytes, Integer offset, String version, String id, int mid) { public void sendNextStep(DeviceLogDTO logDto, String path, MultipartFile file, int length, byte[] bytes, Integer offset, String version, String id, int mid, String fileCheck) {
try { try {
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
Thread.sleep(100); Thread.sleep(300);
FileRedisDto fileRedisDto = (FileRedisDto) redisUtil.getObjectByKey("uploadFileStep"); FileRedisDto fileRedisDto = (FileRedisDto) redisUtil.getObjectByKey("uploadFileStep");
FileRedisDto fileRedis = new FileRedisDto(); FileRedisDto fileRedis = new FileRedisDto();
if (Objects.nonNull(fileRedisDto.getCode()) && fileRedisDto.getCode().equals(200)) { if (Objects.nonNull(fileRedisDto.getCode()) && fileRedisDto.getCode().equals(200)) {
fileRedis.setCode(200); fileRedis.setCode(200);
break; break;
} else { } else {
ReqAndResDto.Req req = getPojo(mid,path,file,length,bytes,offset); ReqAndResDto.Req req = getPojo(mid,path,file,length,bytes,offset,fileCheck);
publisher.send("/Pfm/DevFileCmd/" + version + "/" + id, new Gson().toJson(req), 1, false); publisher.send("/Pfm/DevFileCmd/" + version + "/" + id, new Gson().toJson(req), 1, false);
logDto.setOperate(id + "系统上送文件,装置响应失败,重新发送,这是第" + (i+1) + ""); logDto.setOperate(id + "系统上送文件,装置响应失败,重新发送,这是第" + (i+1) + "");
logDto.setResult(1); logDto.setResult(1);

View File

@@ -0,0 +1,52 @@
package com.njcn.access.utils;
/**
* @author xy
*/
public class CRC32Utils {
// CRC-32/MPEG-2 多项式, x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
private static final int POLYNOMIAL = 0x04C11DB7;
public static int calculateCRC32(byte[] buf, int len, int seed) {
if (buf == null || len <= 0) {
return seed;
}
int crc = seed;
int count = 0;
// 对长度进行填充以适应32位整数
int rem = len % Integer.BYTES;
if (rem > 0) {
int n = Integer.BYTES - rem;
byte[] newBuf = new byte[len + n];
System.arraycopy(buf, 0, newBuf, 0, len);
// 填充字节用0xFF
for (int i = len; i < len + n; i++) {
newBuf[i] = (byte) 0xFF;
}
buf = newBuf;
len += n;
}
int uiCount = len / Integer.BYTES;
for (int k = 0; k < uiCount; k++) {
int uiTemp = 0;
for (int i = 0; i < Integer.BYTES; i++) {
uiTemp |= (buf[k * Integer.BYTES + i] & 0xFF) << (8 * (3 - i));
}
for (int j = 0; j < 32; j++) {
// 检查最高位是否为1
if ((crc ^ uiTemp) < 0) {
crc = 0x04C11DB7 ^ (crc << 1);
count ++;
} else {
crc <<= 1;
}
uiTemp <<= 1;
}
}
return crc;
}
}