1.首先从所有文件服务器获取文件,并组成新的集合:
//clientList为文件服务器实体类集合
clientList.forEach(c -> {
SMBClient client = new SMBClient();
try (Connection connection = client.connect(c.getSourceIp())) {
//将账号和密码放入session中
AuthenticationContext ac = new AuthenticationContext(c.getUsername(), c.getPassword().toCharArray(), "");
Session session = connection.authenticate(ac);
try (DiskShare share = (DiskShare) session.connectShare(c.getShareName())) {
//开始获取共享文件夹数据
List<FileIdBothDirectoryInformation> fileInformations = new ArrayList<>();
share.list(c.getPath(), "*.xlsx").forEach(f -> {
if (null != f.getLastWriteTime()){
FileTime lastWriteTime = f.getLastWriteTime();
DateTime offsetMinute = DateUtil.offsetMinute(lastWriteTime.toDate(), 5);
//如果最后写入时间与当前时间小于5分钟
if(!offsetMinute.isAfter(new DateTime())){
fileInformations.add(f);
}
}
});
CountDownLatch countDownLatch = cutAndResolutionList(fileInformations, share, c.getPath());
countDownLatch.await();
} catch (Exception e) {
e.printStackTrace();
log.error("解析Excel任务异常",e);
}
}catch (IOException e) {
e.printStackTrace();
log.error("解析Excel任务异常",e);
}finally {
client.close();
}
});
2.根据文件大小决定划分线程数
private CountDownLatch cutAndResolutionList(List<FileIdBothDirectoryInformation> needResolutionFile, DiskShare share, String path) {
if(CollUtil.isEmpty(needResolutionFile)) {
return new CountDownLatch(0);
}
if(needResolutionFile.size() >= 3) {//文件数据大于3时,分为3个线程
int runSize = 3;
int remainder = needResolutionFile.size() % runSize; //(先计算出余数)
int number = needResolutionFile.size() / runSize; //然后是商
int offset = 0;//偏移量
CountDownLatch countDownLatch = new CountDownLatch(3);
for (int i = 0; i < runSize; i++) {
List<FileIdBothDirectoryInformation> threadList = null;
if (remainder > 0) {
threadList = needResolutionFile.subList(i * number + offset, (i + 1) * number + offset + 1);
remainder--;
offset++;
} else {
threadList = needResolutionFile.subList(i * number + offset, (i + 1) * number + offset);
}
CsvResolver csvResolverTread = new CsvResolver(threadList, share, countDownLatch, remoteAoiService, path);
threadPoolTaskExecutor.execute(csvResolverTread);
}
return countDownLatch;
}else {//文件数量小于3时,只使用一个线程处理
CountDownLatch countDownLatch = new CountDownLatch(1);
ExcelResolver csvResolverTread = new ExcelResolver(needResolutionFile, share, countDownLatch, remoteAoiService, path);
threadPoolTaskExecutor.execute(csvResolverTread);
return countDownLatch;
}
}
3.通过线程解析对应的文件数据
class ExcelResolver implements Runnable {
private final List<FileIdBothDirectoryInformation> fileInformations;
private final DiskShare share;
private final CountDownLatch countDownLatch;
private final RemoteAoiServiceImpl remoteAoiService;
private final String path;
public ExcelResolver (List<FileIdBothDirectoryInformation> fileInformations, DiskShare share, CountDownLatch countDownLatch, RemoteAoiServiceImpl remoteAoiService, String path) {
this.fileInformations = fileInformations;
this.share = share;
this.countDownLatch = countDownLatch;
this.remoteAoiService = remoteAoiService;
this.path = path;
}
@Override
public void run() {
try {
for (FileIdBothDirectoryInformation f : fileInformations) {
String fileName = f.getFileName();
long startTime = System.currentTimeMillis();
// File 转 MultipartFile
MultipartFile mockMultipartFile = null;
com.hierynomus.smbj.share.File file1 = null;
try {
String filePath1 ="";
if(StrUtil.isNotEmpty(path)){
filePath1 = path+"\\";
}
file1 = share.openFile(filePath1+fileName, EnumSet.of(AccessMask.GENERIC_READ), null, SMB2ShareAccess.ALL, SMB2CreateDisposition.FILE_OPEN, null);
mockMultipartFile = new MockMultipartFile(fileName, file1.getInputStream());
} catch (Exception e) {
log.error("文件转换出错,文件名称为:{}",fileName, e);
continue;
}
String machineId = "";
//复制一个流
try {
//根据场内设备Id找到系统内设备id 拼接表名
String substring = fileName.substring(0, fileName.indexOf("-"));
MachineInfoVo machineInfo = baseMapper.selectMachineByEncoded(substring);
if (ObjectUtil.isEmpty(machineInfo) || StrUtil.isEmpty(machineInfo.getMachId())) {
log.info("根据表名未查询到对应设备,跳过");
continue;
}
// step 2 拿回来Excel文件解析(具体解析内容根据实际情况处理)
List<CheckData> excelData = parseExcelData(mockMultipartFile);
} catch (Exception ignored) {
log.error("有文件出错:" + fileName + "ignored:::" + ignored);
} finally {
// step 3 将已经解析过的文件移动到自己的服务器
// step 3.1 写到自己的服务器
FileUtil.mkdir(targetUrl + machineId + "/");
File targetFile = new File(targetUrl + machineId + "/" + fileName);
try{
if (!targetFile.exists()) {
FileUtil.writeFromStream(file1.getInputStream(), targetFile);
}
//step 3.2 删除共享文件夹中的文件
String filePath1 ="";
if(StrUtil.isNotEmpty(path)){
filePath1 = path+"\\";
}
share.rm(filePath1+f.getFileName());
}catch (Exception e) {
log.error(fileName + "文件导出或删除出错,请检查:", e);
}
}
}
}catch (Exception e) {
log.error("excel解析异常",e);
}
countDownLatch.countDown();
}