using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using WIDESEAWCS_Core; using WIDESEAWCS_Core.BaseServices; using WIDESEAWCS_ISystemRepository; using WIDESEAWCS_ISystemServices; using WIDESEAWCS_Model.Models; namespace WIDESEAWCS_SystemServices { public class Sys_LogService : ServiceBase, ISys_LogService { private readonly string[] LogFolders = new[] { "Log", "Log_PLCReadWrite" }; private int fileId = 2020; public Sys_LogService(ISys_LogRepository BaseDal) : base(BaseDal) { } public WebResponseContent GetLogName() { WebResponseContent content = new WebResponseContent(); try { var data = new List(); fileId = 2020; // 重置ID foreach (string folderName in LogFolders) { var folderPath = Path.Combine(AppContext.BaseDirectory, folderName); var folderInfo = new DirectoryInfo(folderPath); if (!folderInfo.Exists) { continue; } var folderData = BuildFolderTree(folderInfo, folderName); data.Add(folderData); } return data.Any() ? WebResponseContent.Instance.OK(data: data) : WebResponseContent.Instance.Error("未找到日志文件夹"); } catch (Exception ex) { return WebResponseContent.Instance.Error(ex.Message); } } public WebResponseContent GetLog(string fileName) { try { if (string.IsNullOrEmpty(fileName)) { return WebResponseContent.Instance.Error("文件名不能为空"); } FileSearchResult searchResult = null; foreach (string folderName in LogFolders) { var folderPath = Path.Combine(AppContext.BaseDirectory, folderName); var folderInfo = new DirectoryInfo(folderPath); if (!folderInfo.Exists) { continue; } searchResult = FindFileWithInfo(folderInfo, fileName, folderName); if (searchResult != null) { break; } } if (searchResult == null) { return WebResponseContent.Instance.Error($"未找到日志文件: {fileName}"); } // 读取文件内容 var fileContent = ReadLogFileContent(searchResult.File.FullName); // 返回包含元数据的结果 var result = new { fileName = searchResult.File.Name, fullPath = searchResult.File.FullName, fatherNode = searchResult.SourceFolder, fileSize = GetFileSize(searchResult.File.Length), lastWriteTime = searchResult.File.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss"), content = fileContent, lineCount = fileContent.Count }; return WebResponseContent.Instance.OK(data: result); } catch (IOException ex) { if (IsFileLockedException(ex)) { return WebResponseContent.Instance.Error($"日志文件正在被系统写入,请稍后再试"); } return WebResponseContent.Instance.Error($"打开日志文件错误,{ex.Message}"); } catch (Exception ex) { return WebResponseContent.Instance.Error($"打开日志文件错误,{ex.Message}"); } } #region MyRegion private object BuildFolderTree(DirectoryInfo folder, string displayName) { var children = new List(); // 处理子目录 foreach (var subDir in folder.GetDirectories().Where(x => x.Name != "Info").OrderByDescending(x => x.CreationTime)) { var files = subDir.GetFiles() .Select(file => new { label = file.Name, id = fileId++, hidden = true, fatherNode = subDir.Name, fullPath = file.FullName, lastWriteTime = file.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss") }) .ToList(); if (files.Any()) { children.Add(new { label = subDir.Name, children = files, id = subDir.Name.GetHashCode(), hidden = false }); } } // 处理根目录文件 var rootFiles = folder.GetFiles() .Select(file => new { label = file.Name, id = fileId++, hidden = true, fatherNode = folder.Name, fullPath = file.FullName, lastWriteTime = file.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss") }) .ToList(); if (rootFiles.Any()) { children.Add(new { label = folder.Name, children = rootFiles, id = folder.Name.GetHashCode(), hidden = false }); } return new { label = displayName, children = children, id = displayName.GetHashCode(), hidden = false, fatherNode = folder.Name, isRoot = true }; } private List ReadLogFileContent(string filePath) { var lines = new List(); using (FileStream stream = new FileStream( filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) using (StreamReader reader = new StreamReader(stream, Encoding.UTF8)) { // 如果文件太大,只读取最后1000行(可选) var fileInfo = new FileInfo(filePath); if (fileInfo.Length > 5 * 1024 * 1024) // 大于5MB { return ReadLastLines(reader, 1000); } // 读取全部内容 while (!reader.EndOfStream) { var line = reader.ReadLine(); lines.Add(line); } } return lines; } private List ReadLastLines(StreamReader reader, int lineCount) { var lines = new Queue(); string line; while ((line = reader.ReadLine()) != null) { lines.Enqueue(line); if (lines.Count > lineCount) { lines.Dequeue(); } } return lines.ToList(); } /// /// 文件查找结果 /// private class FileSearchResult { public FileInfo File { get; set; } public string SourceFolder { get; set; } } /// /// 查找文件并返回详细信息 /// private FileSearchResult FindFileWithInfo(DirectoryInfo folder, string fileName, string sourceFolder) { // 查找当前目录 var file = folder.GetFiles().FirstOrDefault(x => x.Name == fileName); if (file != null) { return new FileSearchResult { File = file, SourceFolder = sourceFolder }; } // 递归查找子目录 foreach (var subDir in folder.GetDirectories().Where(x => x.Name != "Info")) { var result = FindFileWithInfo(subDir, fileName, sourceFolder); if (result != null) { return result; } } return null; } /// /// 获取可读的文件大小 /// private string GetFileSize(long bytes) { string[] sizes = { "B", "KB", "MB", "GB" }; double len = bytes; int order = 0; while (len >= 1024 && order < sizes.Length - 1) { order++; len = len / 1024; } return $"{len:0.##} {sizes[order]}"; } private bool IsFileLockedException(IOException ex) { int errorCode = ex.HResult & 0xFFFF; return errorCode == 32 || errorCode == 33; // ERROR_SHARING_VIOLATION or ERROR_LOCK_VIOLATION } #endregion } }