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 _options; /// /// 配置 /// private readonly Microsoft.Extensions.Configuration.IConfiguration _configuration; /// /// GUID生成 /// private readonly IGuidGenerator _guidGenerator; #region 变量 /// /// 错误信息前缀 /// private static string _errorMessagePrefix => System.Reflection.MethodBase.GetCurrentMethod()?.DeclaringType?.Name + "."; private int _transferFileCountPerTime; /// /// 每次传输文件数量(工作目录到备份目录) /// public int TransferFileCountPerTime { get { if (_transferFileCountPerTime == 0) { _transferFileCountPerTime = _configuration["ConfigDic:TransferFileCountPerTime"].TryToInt() ?? 50; } return _transferFileCountPerTime; } } #endregion public JisFileReadingWorker( AbpAsyncTimer timer, IOptions 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 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; } /// /// 将报文从接收目录移动到工作目录 /// /// 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); } } /// /// 工作目录中文件保存到数据库 /// /// /// public virtual async Task> WorkDirFileToDatabase(PathConfigInfo cfgInfo, PeriodicBackgroundWorkerContext workerContext) { List retLst = new List(); //批量读取工作目录文件 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(); 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(); } /// /// 将报文从工作目录移动到备份目录 /// /// /// 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); } } /// /// 将报文从工作目录移动到备份目录的重复文件夹 /// /// /// 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); } } /// /// 将报文从工作目录移动到错误目录 /// /// /// 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 }