文件校验
This commit is contained in:
@@ -30,4 +30,8 @@ public class UploadFileDto {
|
|||||||
@ApiModelProperty("文件包数据")
|
@ApiModelProperty("文件包数据")
|
||||||
private String data;
|
private String data;
|
||||||
|
|
||||||
|
@SerializedName("FileCheck")
|
||||||
|
@ApiModelProperty("文件校验码")
|
||||||
|
private String fileCheck;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user