You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

429 lines
16 KiB

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Volo.Abp.BackgroundWorkers;
using Volo.Abp.Guids;
using Volo.Abp.Threading;
using Volo.Abp.Uow;
using Win_in.Sfs.Wms.DataExchange.Domain.Shared;
using Win_in.Sfs.Wms.DataExchange.MesAgent.ReadFiles;
namespace Win_in.Sfs.Wms.DataExchange.MesAgent;
public class JisFileReadingWorker : AsyncPeriodicBackgroundWorkerBase
{
private readonly IOptions<DataExchangeOptions> _options;
/// <summary>
/// 配置
/// </summary>
private readonly Microsoft.Extensions.Configuration.IConfiguration _configuration;
/// <summary>
/// GUID生成
/// </summary>
private readonly IGuidGenerator _guidGenerator;
#region 变量
/// <summary>
/// 错误信息前缀
/// </summary>
private static string _errorMessagePrefix => System.Reflection.MethodBase.GetCurrentMethod()?.DeclaringType?.Name + ".";
private int _transferFileCountPerTime;
/// <summary>
/// 每次传输文件数量(工作目录到备份目录)
/// </summary>
public int TransferFileCountPerTime
{
get
{
if (_transferFileCountPerTime == 0)
{
_transferFileCountPerTime = _configuration["ConfigDic:TransferFileCountPerTime"].TryToInt() ?? 50;
}
return _transferFileCountPerTime;
}
}
#endregion
public JisFileReadingWorker(
AbpAsyncTimer timer,
IOptions<DataExchangeOptions> options,
Microsoft.Extensions.Configuration.IConfiguration configuration,
IGuidGenerator guidGenerator,
IServiceScopeFactory serviceScopeFactory
) : base(timer, serviceScopeFactory)
{
_options = options;
Timer.Period = options.Value.ReadingFilesOptions.PeriodSeconds * 1000; //default 5 minutes
_configuration = configuration;
_guidGenerator = guidGenerator;
}
[UnitOfWork]
protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext)
{
Logger.LogInformation("GetFiles:Starting: Handling Jis File Reading...");
if (!_options.Value.ReadingFilesOptions.Active)
{
Logger.LogInformation("GetFiles:Jis File Reading is not active!");
return;
}
//Timer.Stop(); //运行期间,暂定计时
await GetEdiData(workerContext).ConfigureAwait(false);
//Timer.Start(); //运行结束,开启计时
Logger.LogInformation("GetFiles:Completed: Handling Jis File Reading...");
}
#region 私有方法
public virtual async Task<PathConfigInfo> GetEdiData(PeriodicBackgroundWorkerContext workerContext)
{
//初始化目录
PathConfigInfo cfgInfo = ReadConfig();
//接收目录到工作目录
int fileCnt = ReceToWorkDir(cfgInfo);
//工作目录报文保存到数据库
var lst = await WorkDirFileToDatabase(cfgInfo, workerContext).ConfigureAwait(false);
Logger.LogInformation("GetFiles:接收{0}个报文,其中入库{1}个!", fileCnt, lst.Count);
return cfgInfo;
}
private PathConfigInfo ReadConfig()
{
_ = new PathConfigInfo("", "", "", "", "");
PathConfigInfo ret;
#region 取目录配置
try
{
string receiveDir = _configuration["ConfigDic:PathRead:接收目录"];
string workDir = _configuration["ConfigDic:PathRead:工作目录"];
string bakDir = _configuration["ConfigDic:PathRead:备份目录"];
string errorDir = _configuration["ConfigDic:PathRead:错误目录"];
string waitDir = _configuration["ConfigDic:PathRead:等待目录"];
string pathReadType = _configuration["ConfigDic:PathReadType"];
if (pathReadType != null && pathReadType == "绝对")
{
ret = new PathConfigInfo(receiveDir, workDir, bakDir, errorDir, waitDir);
}
else
{
ret = new PathConfigInfo(
GetAbsPath(receiveDir),
GetAbsPath(workDir),
GetAbsPath(bakDir),
GetAbsPath(errorDir),
GetAbsPath(waitDir)
);
}
}
catch (Exception ex)
{
string errorMsg = "文件传输-取目录配置时出错:" + ex.Message;
throw new Exception(errorMsg);
}
#endregion
#region 创建目录
try
{
if (!Directory.Exists(ret.ReceivePath))
{
Directory.CreateDirectory(ret.ReceivePath);
}
if (!Directory.Exists(ret.WorkPath))
{
Directory.CreateDirectory(ret.WorkPath);
}
if (!Directory.Exists(ret.BakPath))
{
Directory.CreateDirectory(ret.BakPath);
}
if (!Directory.Exists(ret.ErrorPath))
{
Directory.CreateDirectory(ret.ErrorPath);
}
if (!Directory.Exists(ret.WaitPath))
{
Directory.CreateDirectory(ret.WaitPath);
}
string ymd = DateTime.Now.ToString("yyyy-MM-dd");
string bakChildPath = Path.Combine(ret.BakPath, ymd);
if (!Directory.Exists(bakChildPath))
{
Directory.CreateDirectory(bakChildPath);
}
//string ymdRepeat = "重复文件" + DateTime.Now.ToString("yyyy-MM-dd");
//string bakRepeatChildPath = Path.Combine(ret.BakPath, ymd);
}
catch (Exception ex)
{
string errorMsg = "文件传输-创建目录出错:" + ex.Message;
throw new Exception(errorMsg);
}
#endregion
#region 取报文过滤关键字
try
{
string fileFilterKeyword = _configuration["ConfigDic:FileFilterKeyword"];
ret.SetFileFilterKeyword(fileFilterKeyword);
}
catch (Exception ex)
{
string errorMsg = "文件传输-取报文过滤关键字配置时出错或没有配置数据:" + ex.Message;
throw new Exception(errorMsg);
}
#endregion
return ret;
}
/// <summary>
/// 将报文从接收目录移动到工作目录
/// </summary>
/// <returns></returns>
private int ReceToWorkDir(PathConfigInfo cfgInfo)
{
int ret = 0;
DirectoryInfo receiveDir = new DirectoryInfo(cfgInfo.ReceivePath);
FileInfo[] receiveFileLst = receiveDir.GetFiles(cfgInfo.FileFilterKeyword, SearchOption.TopDirectoryOnly); //批量读取接收目录文件
try
{
if (receiveFileLst.Length > 0)
{
receiveFileLst = receiveFileLst.Where(itm => itm.Length > 0).OrderBy(itm => itm.LastWriteTime).ToArray(); //Take(TransferFileCountPerTime)
ret = receiveFileLst.Length;
foreach (FileInfo receiveFileObj in receiveFileLst) //遍历接收目录文件
{
string workFileFullName = Path.Combine(cfgInfo.WorkPath, receiveFileObj.Name);
receiveFileObj.MoveTo(workFileFullName, true);
}
}
else //接收目录没有文件时从等待目录接收
{
DirectoryInfo waitDir = new DirectoryInfo(cfgInfo.WaitPath);
FileInfo[] waitFileLst = waitDir.GetFiles(cfgInfo.FileFilterKeyword, SearchOption.TopDirectoryOnly);
if (waitFileLst.Length > 0)
{
waitFileLst = waitFileLst.OrderBy(itm => itm.LastWriteTime).Take(TransferFileCountPerTime).ToArray();
foreach (FileInfo waitFileItm in waitFileLst) //遍历接收目录文件
{
string workFileFullName = Path.Combine(cfgInfo.WorkPath, waitFileItm.Name);
waitFileItm.MoveTo(workFileFullName, true);
}
}
}
return ret;
}
catch (Exception ex)
{
string errorMsg = $"将多个报文从接收目录移动到工作目录时报错:{ex.Message}";
throw new Exception(errorMsg);
}
}
/// <summary>
/// 工作目录中文件保存到数据库
/// </summary>
/// <param name="cfgInfo"></param>
/// <returns></returns>
public virtual async Task<List<MessageReceiveDTO>> WorkDirFileToDatabase(PathConfigInfo cfgInfo, PeriodicBackgroundWorkerContext workerContext)
{
List<MessageReceiveDTO> retLst = new List<MessageReceiveDTO>();
//批量读取工作目录文件
DirectoryInfo workDir = new DirectoryInfo(cfgInfo.WorkPath);
FileInfo[] workFileLst = workDir.GetFiles(cfgInfo.FileFilterKeyword, SearchOption.TopDirectoryOnly);
workFileLst = workFileLst.OrderBy(itm => itm.LastWriteTime).Take(TransferFileCountPerTime).ToArray();
//遍历【工作目录】文件
foreach (FileInfo workFileObj in workFileLst)
{
string fileName = workFileObj.Name;
Logger.LogInformation($"GetFiles:{fileName}=>WorkDirFileToDatabase,开始加载IMessageReceiveAppService。。。");
//Resolve dependencies
var messageReceiveAppService = workerContext
.ServiceProvider
.GetRequiredService<QAD.IMessageReceiveAppService>();
Logger.LogInformation($"GetFiles:{fileName}=>WorkDirFileToDatabase,加载IMessageReceiveAppService完毕!");
if (fileName.TrimEnd(workFileObj.Extension.ToCharArray()).EndsWith(((int)EnumFileTypeStatus.Add).ToString()))
{
var exsitFileInfo = await messageReceiveAppService.GetByFileNameAsync(fileName).ConfigureAwait(false);
//确认文件是否已经的读取过,已经读取过就把文件放到备份目录的重复文件夹
if (exsitFileInfo != null)
{
WorkDirToBakRepeatDir(cfgInfo, fileName); ////将文件从【工作目录】移动到【备份目录的重复文件夹】
Logger.LogInformation($"GetFiles:{fileName}=>文件已经保存过,将文件从【工作目录】移动到【备份目录的重复文件夹】。");
continue;
}
}
Logger.LogInformation($"GetFiles:{fileName}=>GetByFileNameAsync 获取结束,无此文件的历史信息,可以继续读取数据!");
string fileSimpleName = workFileObj.Name.Replace(workFileObj.Extension, "");
string upinsetType = fileSimpleName.Substring(fileSimpleName.Length - 2);
try
{
//读取工作文件内容
StreamReader sr = workFileObj.OpenText();
var text = await sr.ReadToEndAsync().ConfigureAwait(false);
sr.Close();
//保存到报文接收表
var msgReceiveObj = new MessageReceiveInput()
{
TraceId = _guidGenerator.Create().ToString(),
MessageFileName = fileName,
MessageContent = text,
ReceiveStatus = EnumReceiveStatus.Received,
ReceiveTime = DateTime.Now,
LastUpdateTime = workFileObj.LastWriteTime,
Type = upinsetType,
ErrorCount = 0,
ErrorMessage = "",
};
Logger.LogInformation($"GetFiles:{fileName}=>WorkDirFileToDatabase,开始保存文件{fileName}信息。。。");
Logger.LogInformation($"GetFiles:{fileName}=>变量 TraceId,值={msgReceiveObj.TraceId}");
Logger.LogInformation($"GetFiles:{fileName}=>变量 MessageFileName,值={fileName}");
Logger.LogInformation($"GetFiles:{fileName}=>变量 MessageContent,值={text}");
Logger.LogInformation($"GetFiles:{fileName}=>变量 ReceiveStatus,值={EnumReceiveStatus.Received}");
Logger.LogInformation($"GetFiles:{fileName}=>变量 ReceiveTime,值={msgReceiveObj.ReceiveTime}");
Logger.LogInformation($"GetFiles:{fileName}=>变量 Type,值={upinsetType}");
Logger.LogInformation($"GetFiles:{fileName}=>变量 ErrorCount,值={0}");
Logger.LogInformation($"GetFiles:{fileName}=>变量 ErrorMessage,值={""}");
var succObj = await messageReceiveAppService.AddAsync(msgReceiveObj).ConfigureAwait(false);
Logger.LogInformation($"GetFiles:{fileName}=>WorkDirFileToDatabase,保存文件{fileName}信息结束");
if (succObj != null)
{
WorkDirToBakDir(cfgInfo, fileName); //将文件从【工作目录】移动到【备份目录】
retLst.Add(succObj);
}
else
{
WorkDirToErrorDir(cfgInfo, fileName); //将文件从【工作目录】移动到【错误目录】
string msg = $"将报文{fileName}保存到数据库时失败";
//_logRemindDomainService.WriteLogRemind("报文传输", msg, LogTypeEnum.None);
Logger.LogError(_errorMessagePrefix + msg);
}
}
catch (Exception ex)
{
string errorMsg = $"调用WorkDirFileToDatabase方法时报错:{fileName}:{ex.Message}";
string errorMsg2 = $"调用WorkDirFileToDatabase方法时报错:{fileName}:{ex.ToString()}";
//_logRemindDomainService.WriteLogRemind("报文保存到数据库", errorMsg, LogTypeEnum.None);
Logger.LogError(_errorMessagePrefix + errorMsg);
Logger.LogError(_errorMessagePrefix + errorMsg2);
}
}//循环);
return retLst.ToList();
}
/// <summary>
/// 将报文从工作目录移动到备份目录
/// </summary>
/// <param name="workFileFullName"></param>
/// <param name="bakFileFullName"></param>
private static void WorkDirToBakDir(PathConfigInfo cfgInfo, string fileName)
{
string ymd = DateTime.Now.ToString("yyyy-MM-dd");
string bakChildPath = Path.Combine(cfgInfo.BakPath, ymd); //备份目录每天创建一个子目录
string workFileFullName = Path.Combine(cfgInfo.WorkPath, fileName);
string bakFileFullName = Path.Combine(bakChildPath, fileName);
if (File.Exists(workFileFullName))
{
File.Move(workFileFullName, bakFileFullName, true);
}
}
/// <summary>
/// 将报文从工作目录移动到备份目录的重复文件夹
/// </summary>
/// <param name="workFileFullName"></param>
/// <param name="bakFileFullName"></param>
private static void WorkDirToBakRepeatDir(PathConfigInfo cfgInfo, string fileName)
{
string ymd = "重复文件" + DateTime.Now.ToString("yyyy-MM-dd");
string bakChildPath = Path.Combine(cfgInfo.BakPath, ymd); //备份目录每天创建一个子目录
string workFileFullName = Path.Combine(cfgInfo.WorkPath, fileName);
string bakFileFullName = Path.Combine(bakChildPath, fileName);
if (!Directory.Exists(bakChildPath))
{
Directory.CreateDirectory(bakChildPath);
}
if (File.Exists(workFileFullName))
{
File.Move(workFileFullName, bakFileFullName, true);
}
}
/// <summary>
/// 将报文从工作目录移动到错误目录
/// </summary>
/// <param name="workFileFullName"></param>
/// <param name="bakFileFullName"></param>
private static void WorkDirToErrorDir(PathConfigInfo cfgInfo, string fileName)
{
string workFileFullName = Path.Combine(cfgInfo.WorkPath, fileName);
string errFileFullName = Path.Combine(cfgInfo.ErrorPath, fileName);
if (File.Exists(workFileFullName))
{
File.Move(workFileFullName, errFileFullName, true);
}
}
private static string GetAbsPath(string sourcePath)
{
if (sourcePath.Trim().StartsWith("."))
{
string childPath = sourcePath.Trim().Replace("/", "\\").Replace(".\\", "");
string rootPath = System.Environment.CurrentDirectory;
string ret = Path.Combine(rootPath, childPath);
return ret;
}
else
{
return sourcePath;
}
}
#endregion
}