From f4638b691a4f678a7a6e7515e30afa706bc604b8 Mon Sep 17 00:00:00 2001
From: huangxiaoqiang <huangxiaoqiang@hnkhzn.com>
Date: 星期六, 13 十二月 2025 10:19:03 +0800
Subject: [PATCH] 1
---
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/System/Sys_LogController.cs | 250 +++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 227 insertions(+), 23 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 3a72445..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"
@@ -16,9 +16,16 @@
[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()
{
@@ -81,21 +88,44 @@
if (files.Count > 0)
{
FileInfo file = files.Where(x => x.Name == fileName).FirstOrDefault();
- using StreamReader stream = new StreamReader(file.FullName);
- StringBuilder text = new StringBuilder();
- List<string> lines = new List<string>();
- int i = 0;
- while (stream.Peek() >= 0)
+ if (file == null)
{
- var line = stream.ReadLine();
- lines.Add(line);
+ return WebResponseContent.Instance.Error($"鏈壘鍒版棩蹇楁枃浠�: {fileName}");
}
- content = WebResponseContent.Instance.OK(data: lines);
+ // 浣跨敤鍏变韩璇诲彇妯″紡
+ 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)
@@ -104,8 +134,9 @@
}
return content;
}
+
[HttpPost, HttpGet, Route("DownLoadLog"), AllowAnonymous]
- public virtual ActionResult DownLoadLog(string fileName)
+ public virtual async Task<ActionResult> DownLoadLog(string fileName)
{
try
{
@@ -113,6 +144,12 @@
if (string.IsNullOrWhiteSpace(fileName))
{
return BadRequest("鏂囦欢鍚嶄笉鑳戒负绌�");
+ }
+
+ // 瀹夊叏鎬ф鏌ワ細闃叉璺緞閬嶅巻鏀诲嚮
+ if (fileName.Contains("..") || Path.IsPathRooted(fileName))
+ {
+ return BadRequest("鏃犳晥鐨勬枃浠跺悕");
}
//string logDirectory = Path.Combine(AppContext.BaseDirectory, "logs");
@@ -138,22 +175,26 @@
FileInfo fileInfo = new FileInfo(filePath);
- if (fileInfo.Length > 50 * 1024 * 1024) // 50MB闄愬埗
+ if (fileInfo.Length > MAX_FILE_SIZE_MB * 1024 * 1024)
{
- return BadRequest("鏂囦欢杩囧ぇ锛屾棤娉曚笅杞�");
+ return BadRequest($"鏂囦欢杩囧ぇ锛岃秴杩噞MAX_FILE_SIZE_MB}MB闄愬埗");
}
- byte[] fileBytes;
- using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
+ // 鏂规1锛氫娇鐢ㄩ噸璇曟満鍒� + 鍏变韩璇诲彇锛堟帹鑽愶級
+ byte[] fileBytes = await ReadFileWithRetryAsync(filePath);
+
+ if (fileBytes == null)
{
- using (MemoryStream memoryStream = new MemoryStream())
- {
- fileStream.CopyTo(memoryStream);
- fileBytes = memoryStream.ToArray();
- }
+ 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);
}
@@ -167,19 +208,79 @@
}
catch (IOException ex)
{
- return StatusCode(500, "鏂囦欢璇诲彇澶辫触锛屽彲鑳芥鍦ㄨ鍏朵粬杩涚▼浣跨敤");
+ if (IsFileLockedException(ex))
+ {
+ return StatusCode(500, "鏂囦欢琚攣瀹氾紝鍙兘姝e湪琚郴缁熷啓鍏ワ紝璇风◢鍚庡啀璇�");
+ }
+ return StatusCode(500, $"鏂囦欢璇诲彇澶辫触: {ex.Message}");
}
catch (Exception ex)
{
+ // 璁板綍寮傚父鏃ュ織锛堣繖閲岀畝鍖栦负杩斿洖锛屽疄闄呴」鐩腑搴旇璁板綍鍒版棩蹇楃郴缁燂級
return StatusCode(500, $"鏈嶅姟鍣ㄥ唴閮ㄩ敊璇�: {ex.Message}");
}
}
- private bool IsAllowedFileType(string extension)
+
+ /// <summary>
+ /// 甯﹂噸璇曟満鍒剁殑鏂囦欢璇诲彇鏂规硶
+ /// </summary>
+ private async Task<byte[]> ReadFileWithRetryAsync(string filePath)
{
- var allowedTypes = new[] { ".txt", ".log", ".csv", ".json", ".xml" };
- return allowedTypes.Contains(extension);
+ 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
@@ -192,5 +293,108 @@
_ => "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