From b680585c3a6d43f0c72a83a115ea537ce8c91a07 Mon Sep 17 00:00:00 2001
From: 647556386 <647556386@qq.com>
Date: 星期六, 13 十二月 2025 17:44:10 +0800
Subject: [PATCH] Merge branch 'master' of http://115.159.85.185:8098/r/ZhongRui/ALDbanyunxiangmu

---
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/System/Sys_LogController.cs |  384 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 382 insertions(+), 2 deletions(-)

diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/System/Sys_LogController.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/System/Sys_LogController.cs"
index 3cd2f46..8fd6406 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/System/Sys_LogController.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/System/Sys_LogController.cs"
@@ -1,5 +1,8 @@
-锘縰sing Microsoft.AspNetCore.Http;
+锘縰sing Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
+using System.Text;
+using WIDESEA_Core;
 using WIDESEA_Core.BaseController;
 using WIDESEA_ISystemService;
 using WIDESEA_Model.Models;
@@ -13,8 +16,385 @@
     [ApiController]
     public class Sys_LogController : ApiBaseController<ISys_LogService, Sys_Log>
     {
+        // 閰嶇疆甯搁噺
+        private const int MAX_FILE_SIZE_MB = 50;
+        private const int MAX_RETRY_COUNT = 3;
+        private const int RETRY_DELAY_MS = 100;
+        private static readonly string[] ALLOWED_FILE_TYPES = { ".txt", ".log", ".csv", ".json", ".xml" };
+
         public Sys_LogController(ISys_LogService service) : base(service)
         {
         }
+
+        [HttpPost, Route("GetLogName"), AllowAnonymous]
+        public WebResponseContent GetLogName()
+        {
+            WebResponseContent content = new WebResponseContent();
+            try
+            {
+                List<object> data = new List<object>();
+                DirectoryInfo folder = new DirectoryInfo(AppContext.BaseDirectory + "\\logs\\");
+                DirectoryInfo[] firstDirectoryInfos = folder.GetDirectories().OrderByDescending(x => x.CreationTime).ToArray();
+                int k = 2020;
+                for (int i = 0; i < firstDirectoryInfos.Length; i++)
+                {
+                    if (firstDirectoryInfos[i].Name != "Info")
+                    {
+                        FileInfo[] nextFileInfos = firstDirectoryInfos[i].GetFiles();
+                        List<object> values = new List<object>();
+                        for (int j = 0; j < nextFileInfos.Length; j++)
+                        {
+                            values.Add(new { label = nextFileInfos[j].Name, id = k, hidden = true, fatherNode = firstDirectoryInfos[i].Name });
+                            k++;
+                        }
+                        data.Add(new { label = firstDirectoryInfos[i].Name, children = values, id = i, hidden = false });
+                    }
+                }
+
+                FileInfo[] nextFileInfo = folder.GetFiles();
+                List<object> value = new List<object>();
+                for (int j = 0; j < nextFileInfo.Length; j++)
+                {
+                    value.Add(new { label = nextFileInfo[j].Name, id = k, hidden = true, fatherNode = folder.Name });
+                    k++;
+                }
+                data.Add(new { label = folder.Name, children = value, id = 1, hidden = false });
+
+                return WebResponseContent.Instance.OK(data: data);
+            }
+            catch (Exception ex)
+            {
+                return WebResponseContent.Instance.Error(ex.Message);
+            }
+        }
+
+        [HttpPost, Route("GetLog"), AllowAnonymous]
+        public WebResponseContent GetLog(string fileName)
+        {
+            WebResponseContent content = new WebResponseContent();
+            try
+            {
+                List<FileInfo> files = new List<FileInfo>();
+                DirectoryInfo folder = new DirectoryInfo(AppContext.BaseDirectory + "\\logs\\");
+                DirectoryInfo[] firstDirectoryInfos = folder.GetDirectories();
+                for (int i = 0; i < firstDirectoryInfos.Length; i++)
+                {
+                    FileInfo[] nextFileInfos = firstDirectoryInfos[i].GetFiles();
+                    files.AddRange(nextFileInfos);
+                }
+
+                FileInfo[] nextFileInfo = folder.GetFiles();
+                files.AddRange(nextFileInfo);
+                if (files.Count > 0)
+                {
+                    FileInfo file = files.Where(x => x.Name == fileName).FirstOrDefault();
+                    if (file == null)
+                    {
+                        return WebResponseContent.Instance.Error($"鏈壘鍒版棩蹇楁枃浠�: {fileName}");
+                    }
+
+                    // 浣跨敤鍏变韩璇诲彇妯″紡
+                    using (FileStream stream = new FileStream(
+                        file.FullName,
+                        FileMode.Open,
+                        FileAccess.Read,
+                        FileShare.ReadWrite))
+                    using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
+                    {
+                        StringBuilder text = new StringBuilder();
+                        List<string> lines = new List<string>();
+                        while (!reader.EndOfStream)
+                        {
+                            var line = reader.ReadLine();
+                            lines.Add(line);
+                        }
+
+                        content = WebResponseContent.Instance.OK(data: lines);
+                    }
+                }
+                else
+                {
+                    content = WebResponseContent.Instance.Error($"鏈壘鍒版棩蹇楁枃浠�,銆恵fileName}銆�");
+                }
+            }
+            catch (IOException ex)
+            {
+                if (IsFileLockedException(ex))
+                {
+                    content = WebResponseContent.Instance.Error($"鏃ュ織鏂囦欢姝e湪琚郴缁熷啓鍏ワ紝璇风◢鍚庡啀璇�");
+                }
+                else
+                {
+                    content = WebResponseContent.Instance.Error($"鎵撳紑鏃ュ織鏂囦欢閿欒,{ex.Message}");
+                }
+            }
+            catch (Exception ex)
+            {
+                content = WebResponseContent.Instance.Error($"鎵撳紑鏃ュ織鏂囦欢閿欒,{ex.Message}");
+            }
+            return content;
+        }
+
+        [HttpPost, HttpGet, Route("DownLoadLog"), AllowAnonymous]
+        public virtual async Task<ActionResult> DownLoadLog(string fileName)
+        {
+            try
+            {
+                // 1. 鍙傛暟楠岃瘉
+                if (string.IsNullOrWhiteSpace(fileName))
+                {
+                    return BadRequest("鏂囦欢鍚嶄笉鑳戒负绌�");
+                }
+
+                // 瀹夊叏鎬ф鏌ワ細闃叉璺緞閬嶅巻鏀诲嚮
+                if (fileName.Contains("..") || Path.IsPathRooted(fileName))
+                {
+                    return BadRequest("鏃犳晥鐨勬枃浠跺悕");
+                }
+
+                //string logDirectory = Path.Combine(AppContext.BaseDirectory, "logs");
+                string logDirectory = Path.Combine(AppContext.BaseDirectory);
+
+                if (!Directory.Exists(logDirectory))
+                {
+                    Directory.CreateDirectory(logDirectory);
+                }
+
+                string filePath = Path.Combine(logDirectory, fileName);
+
+                if (Directory.Exists(filePath))
+                {
+                    return NotFound($"鏂囦欢 {fileName} 涓嶅瓨鍦�");
+                }
+
+                string extension = Path.GetExtension(fileName).ToLowerInvariant();
+                if (!IsAllowedFileType(extension))
+                {
+                    return BadRequest($"涓嶆敮鎸佺殑鏂囦欢绫诲瀷: {extension}");
+                }
+
+                FileInfo fileInfo = new FileInfo(filePath);
+
+                if (fileInfo.Length > MAX_FILE_SIZE_MB * 1024 * 1024)
+                {
+                    return BadRequest($"鏂囦欢杩囧ぇ锛岃秴杩噞MAX_FILE_SIZE_MB}MB闄愬埗");
+                }
+
+                // 鏂规1锛氫娇鐢ㄩ噸璇曟満鍒� + 鍏变韩璇诲彇锛堟帹鑽愶級
+                byte[] fileBytes = await ReadFileWithRetryAsync(filePath);
+
+                if (fileBytes == null)
+                {
+                    return StatusCode(500, "鏂囦欢琚崰鐢紝鏃犳硶涓嬭浇锛岃绋嶅悗閲嶈瘯");
+                }
+
+                string contentType = GetContentType(extension);
+
+                // 璁剧疆涓嬭浇澶�
+                Response.Headers.Add("Content-Disposition", $"attachment; filename=\"{System.Web.HttpUtility.UrlEncode(fileName, Encoding.UTF8)}\"");
+                Response.Headers.Add("Cache-Control", "no-cache, no-store, must-revalidate");
+                Response.Headers.Add("Pragma", "no-cache");
+                Response.Headers.Add("Expires", "0");
+
+                return File(fileBytes, 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}");
+            }
+        }
+
+        /// <summary>
+        /// 甯﹂噸璇曟満鍒剁殑鏂囦欢璇诲彇鏂规硶
+        /// </summary>
+        private async Task<byte[]> ReadFileWithRetryAsync(string filePath)
+        {
+            for (int attempt = 0; attempt < MAX_RETRY_COUNT; attempt++)
+            {
+                try
+                {
+                    // 浣跨敤 FileShare.ReadWrite 鍏佽鍏朵粬杩涚▼鍚屾椂璇诲彇鍜屽啓鍏�
+                    // 浣跨敤寮傛璇诲彇鎻愰珮鎬ц兘
+                    using (var fileStream = new FileStream(
+                        filePath,
+                        FileMode.Open,
+                        FileAccess.Read,
+                        FileShare.ReadWrite | FileShare.Delete, // 鍏佽鍒犻櫎鎿嶄綔
+                        bufferSize: 4096,
+                        useAsync: true))
+                    {
+                        using (var memoryStream = new MemoryStream())
+                        {
+                            await fileStream.CopyToAsync(memoryStream);
+                            return memoryStream.ToArray();
+                        }
+                    }
+                }
+                catch (IOException) when (attempt < MAX_RETRY_COUNT - 1)
+                {
+                    // 濡傛灉涓嶆槸鏈�鍚庝竴娆¢噸璇曪紝绛夊緟涓�娈垫椂闂�
+                    await Task.Delay(RETRY_DELAY_MS * (attempt + 1));
+                }
+                catch (IOException ex)
+                {
+                    // 鏈�鍚庝竴娆″皾璇曚篃澶辫触浜�
+                    throw;
+                }
+            }
+            return null;
+        }
+
+        /// <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"
+            };
+        }
+
+        /// <summary>
+        /// 澶囬�夋柟妗堬細鍒涘缓涓存椂鍓湰涓嬭浇锛堟渶瀹夊叏锛屼絾鎬ц兘绋嶅樊锛�
+        /// </summary>
+        [HttpPost, HttpGet, Route("DownLoadLogCopy"), AllowAnonymous]
+        public virtual async Task<ActionResult> DownLoadLogCopy(string fileName)
+        {
+            try
+            {
+                // 鍙傛暟楠岃瘉锛堝悓涓婏級
+                if (string.IsNullOrWhiteSpace(fileName))
+                {
+                    return BadRequest("鏂囦欢鍚嶄笉鑳戒负绌�");
+                }
+
+                string logDirectory = Path.Combine(AppContext.BaseDirectory, "logs");
+                string filePath = Path.Combine(logDirectory, fileName);
+
+                if (Directory.Exists(filePath))
+                {
+                    return NotFound($"鏂囦欢 {fileName} 涓嶅瓨鍦�");
+                }
+
+                // 鐢熸垚涓存椂鏂囦欢鍚�
+                string tempFileName = $"{Path.GetFileNameWithoutExtension(fileName)}_{Guid.NewGuid():N}{Path.GetExtension(fileName)}";
+                string tempFilePath = Path.Combine(Path.GetTempPath(), tempFileName);
+
+                try
+                {
+                    // 灏濊瘯澶嶅埗鏂囦欢鍒颁复鏃朵綅缃紙浣跨敤閲嶈瘯鏈哄埗锛�
+                    bool copySuccess = false;
+                    for (int attempt = 0; attempt < MAX_RETRY_COUNT; attempt++)
+                    {
+                        try
+                        {
+                            //Directory.GetFiles.Copy(filePath, tempFilePath, false);
+                            copySuccess = true;
+                            break;
+                        }
+                        catch (IOException) when (attempt < MAX_RETRY_COUNT - 1)
+                        {
+                            await Task.Delay(RETRY_DELAY_MS * (attempt + 1));
+                        }
+                    }
+
+                    if (!copySuccess)
+                    {
+                        return StatusCode(500, "鏃犳硶澶嶅埗鏂囦欢锛屽彲鑳借鍏朵粬杩涚▼鍗犵敤");
+                    }
+
+                    // 浠庝复鏃舵枃浠惰鍙�
+                    byte[] fileBytes;
+                    using (FileStream tempStream = new FileStream(tempFilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
+                    {
+                        using (MemoryStream memoryStream = new MemoryStream())
+                        {
+                            await tempStream.CopyToAsync(memoryStream);
+                            fileBytes = memoryStream.ToArray();
+                        }
+                    }
+
+                    string extension = Path.GetExtension(fileName).ToLowerInvariant();
+                    string contentType = GetContentType(extension);
+
+                    // 杩斿洖鏂囦欢鍚庢竻鐞嗕复鏃舵枃浠�
+                    var result = File(fileBytes, contentType, fileName);
+
+                    // 寮傛娓呯悊涓存椂鏂囦欢
+                    _ = Task.Run(() =>
+                    {
+                        try
+                        {
+                            Directory.Delete(tempFilePath);
+                        }
+                        catch
+                        {
+                            // 蹇界暐鍒犻櫎澶辫触
+                        }
+                    });
+
+                    return result;
+                }
+                finally
+                {
+                    // 纭繚涓存椂鏂囦欢琚竻鐞�
+                    if (Directory.Exists(tempFilePath))
+                    {
+                        try
+                        {
+                            Directory.Delete(tempFilePath);
+                        }
+                        catch
+                        {
+                            // 蹇界暐鍒犻櫎澶辫触
+                        }
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                return StatusCode(500, $"鏈嶅姟鍣ㄥ唴閮ㄩ敊璇�: {ex.Message}");
+            }
+        }
     }
-}
+}
\ No newline at end of file

--
Gitblit v1.9.3