From 960b33fa24c47a330e51a2c24859d681ae62caeb Mon Sep 17 00:00:00 2001
From: huangxiaoqiang <huangxiaoqiang@hnkhzn.com>
Date: 星期四, 16 四月 2026 10:09:49 +0800
Subject: [PATCH] 重构任务与库存模型,增强日志管理与区域接口
---
Code Management/WCS/WIDESEA_WCSServer/WIDESEAWCS_Server/Controllers/System/Sys_LogController.cs | 212 +++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 205 insertions(+), 7 deletions(-)
diff --git a/Code Management/WCS/WIDESEA_WCSServer/WIDESEAWCS_Server/Controllers/System/Sys_LogController.cs b/Code Management/WCS/WIDESEA_WCSServer/WIDESEAWCS_Server/Controllers/System/Sys_LogController.cs
index 5ad637c..f7a730a 100644
--- a/Code Management/WCS/WIDESEA_WCSServer/WIDESEAWCS_Server/Controllers/System/Sys_LogController.cs
+++ b/Code Management/WCS/WIDESEA_WCSServer/WIDESEAWCS_Server/Controllers/System/Sys_LogController.cs
@@ -1,25 +1,28 @@
-锘縰sing Microsoft.AspNetCore.Authorization;
+锘縰sing Autofac.Core;
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
+using System.Text;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.BaseController;
+using WIDESEAWCS_DTO.AGV;
using WIDESEAWCS_ISystemServices;
-using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
-namespace WIDESEAWCS_Server.Controllers.System
+namespace WIDESEAWCSServer.Controllers
{
[Route("api/Sys_Log")]
[ApiController]
public class Sys_LogController : ApiBaseController<ISys_LogService, Sys_Log>
{
+ private const int MAX_FILE_SIZE_MB = 50;
+ private static readonly string[] ALLOWED_FILE_TYPES = { ".txt", ".log", ".csv", ".json", ".xml" };
+ private readonly string[] LogFolders = { "Log", "Log_PLCReadWrite" };
private readonly IHttpContextAccessor _httpContextAccessor;
public Sys_LogController(ISys_LogService service, IHttpContextAccessor httpContextAccessor) : base(service)
{
_httpContextAccessor = httpContextAccessor;
}
-
-
[HttpPost, Route("GetLogList"), AllowAnonymous]
public WebResponseContent GetLogList()
@@ -32,6 +35,201 @@
{
return Service.GetLogData(parm);
}
+
+ [HttpPost, Route("GetLogName"), AllowAnonymous]
+ public WebResponseContent GetLogName()
+ {
+ return Service.GetLogName();
+ }
+
+ [HttpPost, Route("GetLog"), AllowAnonymous]
+ public WebResponseContent GetLog(string fileName)
+ {
+ return Service.GetLog(fileName);
+ }
+
+ [HttpPost, HttpGet, Route("DownLoadLog"), AllowAnonymous]
+ public virtual async Task<ActionResult> DownLoadLog(string fileName)
+ {
+ try
+ {
+ // 鍙傛暟楠岃瘉
+ if (string.IsNullOrWhiteSpace(fileName))
+ {
+ return BadRequest("鏂囦欢鍚嶄笉鑳戒负绌�");
+ }
+
+ // 瀹夊叏鎬ф鏌�
+ if (fileName.Contains("..") || Path.IsPathRooted(fileName) || fileName.Contains("/") || fileName.Contains("\\"))
+ {
+ return BadRequest("鏃犳晥鐨勬枃浠跺悕");
+ }
+
+ // 妫�鏌ユ枃浠剁被鍨�
+ string extension = Path.GetExtension(fileName).ToLowerInvariant();
+ if (!IsAllowedFileType(extension))
+ {
+ return BadRequest($"涓嶆敮鎸佺殑鏂囦欢绫诲瀷: {extension}");
+ }
+
+ // 鏌ユ壘鏂囦欢
+ var fileInfo = await FindLogFileAsync(fileName);
+
+ if (fileInfo == null)
+ {
+ return NotFound($"鏂囦欢 {fileName} 涓嶅瓨鍦�");
+ }
+
+ // 妫�鏌ユ枃浠跺ぇ灏忥紙浠呯敤浜庨檺鍒讹紝涓嶅姞杞藉埌鍐呭瓨锛�
+ if (fileInfo.Length > MAX_FILE_SIZE_MB * 1024 * 1024)
+ {
+ return BadRequest($"鏂囦欢杩囧ぇ锛岃秴杩噞MAX_FILE_SIZE_MB}MB闄愬埗");
+ }
+
+ string contentType = GetContentType(extension);
+
+ // 璁剧疆涓嬭浇澶�
+ Response.Headers.Add("Content-Disposition", $"attachment; filename=\"{System.Web.HttpUtility.UrlEncode(fileName, Encoding.UTF8)}\"");
+ Response.Headers.Add("Content-Length", fileInfo.Length.ToString());
+ Response.Headers.Add("Cache-Control", "no-cache, no-store, must-revalidate");
+ Response.Headers.Add("Pragma", "no-cache");
+ Response.Headers.Add("Expires", "0");
+
+ // 娴佸紡杩斿洖锛屼笉鍔犺浇鏁翠釜鏂囦欢鍒板唴瀛�
+ return File(CreateFileStream(fileInfo.FullName), contentType, fileName);
+ }
+ catch (UnauthorizedAccessException)
+ {
+ return StatusCode(403, "娌℃湁璁块棶璇ユ枃浠剁殑鏉冮檺");
+ }
+ catch (PathTooLongException)
+ {
+ return BadRequest("鏂囦欢璺緞杩囬暱");
+ }
+ catch (IOException ex)
+ {
+ if (IsFileLockedException(ex))
+ {
+ return StatusCode(500, "鏂囦欢琚攣瀹氾紝鍙兘姝e湪琚郴缁熷啓鍏ワ紝璇风◢鍚庡啀璇�");
+ }
+ return StatusCode(500, $"鏂囦欢璇诲彇澶辫触: {ex.Message}");
+ }
+ catch (Exception ex)
+ {
+ return StatusCode(500, $"鏈嶅姟鍣ㄥ唴閮ㄩ敊璇�: {ex.Message}");
+ }
+ }
+
+ private async Task<FileInfo> FindLogFileAsync(string fileName)
+ {
+ var tasks = LogFolders.Select(folderName => Task.Run(() =>
+ {
+ var folderPath = Path.Combine(AppContext.BaseDirectory, folderName);
+ var folderInfo = new DirectoryInfo(folderPath);
+
+ if (!folderInfo.Exists)
+ {
+ return null;
+ }
+
+ return FindFileInFolderAsync(folderInfo, fileName);
+ }));
+
+ var results = await Task.WhenAll(tasks);
+ return results.FirstOrDefault(result => result != null);
+ }
+ private async Task<FileInfo> FindFileInFolderAsync(DirectoryInfo folder, string fileName)
+ {
+ try
+ {
+ // 鍏堟煡鎵惧綋鍓嶇洰褰曚笅鐨勬枃浠�
+ var files = folder.GetFiles();
+ var file = files.FirstOrDefault(x => x.Name.Equals(fileName, StringComparison.OrdinalIgnoreCase));
+
+ if (file != null)
+ {
+ return await Task.FromResult(file);
+ }
+
+ // 閫掑綊鏌ユ壘瀛愮洰褰曪紙鎺掗櫎Info鐩綍锛�
+ foreach (var subDir in folder.GetDirectories())
+ {
+ // 璺宠繃Info鐩綍
+ if (subDir.Name.Equals("Info", StringComparison.OrdinalIgnoreCase))
+ {
+ continue;
+ }
+
+ // 璺宠繃鏃犳硶璁块棶鐨勭洰褰�
+ try
+ {
+ file = await FindFileInFolderAsync(subDir, fileName);
+ if (file != null)
+ {
+ return file;
+ }
+ }
+ catch (UnauthorizedAccessException)
+ {
+ // 璺宠繃鏃犳潈闄愯闂殑鐩綍
+ continue;
+ }
+ }
+ }
+ catch (UnauthorizedAccessException)
+ {
+ // 蹇界暐鏃犳潈璁块棶鐨勭洰褰�
+ }
+ catch (DirectoryNotFoundException)
+ {
+ // 蹇界暐涓嶅瓨鍦ㄧ殑鐩綍
+ }
+
+ return await Task.FromResult<FileInfo>(null);
+ }
+
+ private FileStream CreateFileStream(string filePath)
+ {
+ return new FileStream(
+ filePath,
+ FileMode.Open,
+ FileAccess.Read,
+ FileShare.ReadWrite, // 鍏佽鍏朵粬杩涚▼鍚屾椂璇诲彇/鍐欏叆
+ 81920, // 缂撳啿鍖哄ぇ灏�
+ useAsync: true);
+ }
+
+ /// <summary>
+ /// 鍒ゆ柇鏄惁涓烘枃浠惰閿佸畾鐨勫紓甯�
+ /// </summary>
+ private bool IsFileLockedException(IOException ex)
+ {
+ int errorCode = ex.HResult & 0xFFFF;
+ return errorCode == 32 || errorCode == 33; // ERROR_SHARING_VIOLATION or ERROR_LOCK_VIOLATION
+ }
+
+ /// <summary>
+ /// 妫�鏌ユ枃浠剁被鍨嬫槸鍚﹀厑璁�
+ /// </summary>
+ private bool IsAllowedFileType(string extension)
+ {
+ return ALLOWED_FILE_TYPES.Contains(extension);
+ }
+
+ /// <summary>
+ /// 鑾峰彇Content-Type
+ /// </summary>
+ private string GetContentType(string extension)
+ {
+ return extension.ToLowerInvariant() switch
+ {
+ ".txt" => "text/plain; charset=utf-8",
+ ".log" => "text/plain; charset=utf-8",
+ ".csv" => "text/csv; charset=utf-8",
+ ".json" => "application/json; charset=utf-8",
+ ".xml" => "application/xml; charset=utf-8",
+ _ => "application/octet-stream"
+ };
+ }
}
-
-}
+}
\ No newline at end of file
--
Gitblit v1.9.3