diff --git a/ZR.Admin.WebApi/Controllers/CommonController.cs b/ZR.Admin.WebApi/Controllers/CommonController.cs index 8b693d2..ca1797a 100644 --- a/ZR.Admin.WebApi/Controllers/CommonController.cs +++ b/ZR.Admin.WebApi/Controllers/CommonController.cs @@ -126,12 +126,31 @@ namespace ZR.Admin.WebApi.Controllers switch (storeType) { case StoreType.LOCAL: + logger.Info($"开始本地文件上传 - 文件名: {formFile.FileName}, 大小: {fileSize}KB, 用户: {HttpContext.GetName()}"); + string savePath = Path.Combine(WebHostEnvironment.WebRootPath); + logger.Info($"WebRootPath: {WebHostEnvironment.WebRootPath}"); + if (uploadDto.FileDir.IsEmpty()) { uploadDto.FileDir = OptionsSetting.Upload.LocalSavePath; + logger.Info($"使用默认保存路径: {uploadDto.FileDir}"); + } + else + { + logger.Info($"使用指定保存路径: {uploadDto.FileDir}"); + } + + try + { + sysfile = await SysFileService.SaveFileToLocal(savePath, uploadDto, HttpContext.GetName(), formFile); + logger.Info($"本地文件保存成功 - 文件ID: {sysfile.Id}, 访问URL: {sysfile.AccessUrl}"); + } + catch (Exception ex) + { + logger.Error(ex, $"本地文件保存失败 - 文件名: {formFile.FileName}, 错误: {ex.Message}"); + throw; } - sysfile = await SysFileService.SaveFileToLocal(savePath, uploadDto, HttpContext.GetName(), formFile); break; case StoreType.REMOTE: break; diff --git a/ZR.Admin.WebApi/wwwroot/file/2025/0923/9e02f4efa31ccb89.xlsx b/ZR.Admin.WebApi/wwwroot/file/2025/0923/9e02f4efa31ccb89.xlsx new file mode 100644 index 0000000..02aad15 Binary files /dev/null and b/ZR.Admin.WebApi/wwwroot/file/2025/0923/9e02f4efa31ccb89.xlsx differ diff --git a/ZR.ServiceCore/Services/SysFileService.cs b/ZR.ServiceCore/Services/SysFileService.cs index 727a419..7273266 100644 --- a/ZR.ServiceCore/Services/SysFileService.cs +++ b/ZR.ServiceCore/Services/SysFileService.cs @@ -45,39 +45,92 @@ namespace ZR.ServiceCore.Services /// public async Task SaveFileToLocal(string rootPath, UploadDto dto, string userName, string clasifyType, IFormFile formFile) { + var logger = NLog.LogManager.GetCurrentClassLogger(); + logger.Info($"SaveFileToLocal开始 - 根路径: {rootPath}, 用户: {userName}"); + var fileName = dto.FileName; var fileDir = dto.FileDir; string fileExt = Path.GetExtension(formFile.FileName); fileName = (fileName.IsEmpty() ? HashFileName() : fileName) + fileExt; + logger.Info($"文件名处理完成 - 原始文件名: {dto.FileName}, 最终文件名: {fileName}, 扩展名: {fileExt}"); string filePath = GetdirPath(fileDir); string finalFilePath = Path.Combine(rootPath, filePath, fileName); double fileSize = Math.Round(formFile.Length / 1024.0, 2); + logger.Info($"文件路径构建完成 - 相对路径: {filePath}, 完整路径: {finalFilePath}, 文件大小: {fileSize}KB"); - if (!Directory.Exists(Path.GetDirectoryName(finalFilePath))) + string directoryPath = Path.GetDirectoryName(finalFilePath); + logger.Info($"检查目录是否存在: {directoryPath}"); + + if (!Directory.Exists(directoryPath)) { - Directory.CreateDirectory(Path.GetDirectoryName(finalFilePath)); + logger.Info($"目录不存在,开始创建目录: {directoryPath}"); + try + { + Directory.CreateDirectory(directoryPath); + logger.Info($"目录创建成功: {directoryPath}"); + } + catch (Exception ex) + { + logger.Error(ex, $"目录创建失败: {directoryPath}, 错误: {ex.Message}"); + throw new Exception($"无法创建目录 {directoryPath}: {ex.Message}", ex); + } + } + else + { + logger.Info($"目录已存在: {directoryPath}"); + } + + // 检查目录写入权限 + try + { + logger.Info($"检查目录写入权限: {directoryPath}"); + var testFile = Path.Combine(directoryPath, $"test_{Guid.NewGuid()}.tmp"); + File.WriteAllText(testFile, "test"); + File.Delete(testFile); + logger.Info($"目录写入权限检查通过: {directoryPath}"); + } + catch (Exception ex) + { + logger.Error(ex, $"目录写入权限检查失败: {directoryPath}, 错误: {ex.Message}"); + throw new Exception($"目录 {directoryPath} 没有写入权限: {ex.Message}", ex); } // 常见的图片扩展名 var imageExtensions = new[] { ".jpg", ".jpeg", ".png", ".gif", ".bmp" }; // 检查扩展名是否在图片扩展名列表中 bool isImageByExtension = imageExtensions.Contains(fileExt); - if (dto.Quality > 0 && isImageByExtension) + logger.Info($"文件类型检查 - 是否为图片: {isImageByExtension}, 压缩质量: {dto.Quality}"); + + try { - await SaveCompressedImageAsync(formFile, finalFilePath); - } - else - { - using (var stream = new FileStream(finalFilePath, FileMode.Create)) + if (dto.Quality > 0 && isImageByExtension) { - await formFile.CopyToAsync(stream); + logger.Info($"开始压缩图片保存: {finalFilePath}"); + await SaveCompressedImageAsync(formFile, finalFilePath); + logger.Info($"图片压缩保存完成: {finalFilePath}"); } + else + { + logger.Info($"开始普通文件保存: {finalFilePath}"); + using (var stream = new FileStream(finalFilePath, FileMode.Create)) + { + await formFile.CopyToAsync(stream); + } + logger.Info($"普通文件保存完成: {finalFilePath}"); + } + } + catch (Exception ex) + { + logger.Error(ex, $"文件保存失败: {finalFilePath}, 错误: {ex.Message}"); + throw new Exception($"文件保存失败: {ex.Message}", ex); } string uploadUrl = OptionsSetting.Upload.UploadUrl; string accessPath = string.Concat(filePath.Replace("\\", "/"), "/", fileName); Uri baseUri = new(uploadUrl); Uri fullUrl = new(baseUri, accessPath); + logger.Info($"URL构建完成 - 上传URL: {uploadUrl}, 访问路径: {accessPath}, 完整访问URL: {fullUrl.AbsoluteUri}"); + SysFile file = new(formFile.FileName, fileName, fileExt, fileSize + "kb", filePath, userName) { StoreType = (int)StoreType.LOCAL, @@ -87,7 +140,20 @@ namespace ZR.ServiceCore.Services ClassifyType = clasifyType, CategoryId = dto.CategoryId, }; - file.Id = await InsertFile(file); + + logger.Info($"开始保存文件信息到数据库 - 文件URL: {file.FileUrl}, 访问URL: {file.AccessUrl}"); + try + { + file.Id = await InsertFile(file); + logger.Info($"文件信息保存成功 - 文件ID: {file.Id}"); + } + catch (Exception ex) + { + logger.Error(ex, $"文件信息保存到数据库失败: {ex.Message}"); + throw new Exception($"文件信息保存失败: {ex.Message}", ex); + } + + logger.Info($"SaveFileToLocal完成 - 文件ID: {file.Id}, 访问URL: {file.AccessUrl}"); return file; } //public async Task SaveFileToLocal(string rootPath, string fileName, string fileDir, string userName, IFormFile formFile) @@ -185,23 +251,37 @@ namespace ZR.ServiceCore.Services /// public static async Task SaveCompressedImageAsync(IFormFile formFile, string finalFilePath, int quality = 75) { - using (var image = await Image.LoadAsync(formFile.OpenReadStream())) + var logger = NLog.LogManager.GetCurrentClassLogger(); + logger.Info($"开始压缩图片 - 目标路径: {finalFilePath}, 压缩质量: {quality}"); + + try { - // 进行压缩和调整大小(可选) - //image.Mutate(x => x.Resize(new ResizeOptions - //{ - // Mode = ResizeMode.Max, - // Size = new Size(1920, 1080) // 限制最大尺寸,避免超大图片 - //})); - - // 保存为压缩的 JPEG - var encoder = new JpegEncoder { Quality = quality }; // 质量参数控制压缩程度 - - await using (var stream = new FileStream(finalFilePath, FileMode.Create)) + using (var image = await Image.LoadAsync(formFile.OpenReadStream())) { - await image.SaveAsync(stream, encoder); + logger.Info($"图片加载成功 - 尺寸: {image.Width}x{image.Height}"); + + // 进行压缩和调整大小(可选) + //image.Mutate(x => x.Resize(new ResizeOptions + //{ + // Mode = ResizeMode.Max, + // Size = new Size(1920, 1080) // 限制最大尺寸,避免超大图片 + //})); + + // 保存为压缩的 JPEG + var encoder = new JpegEncoder { Quality = quality }; // 质量参数控制压缩程度 + + await using (var stream = new FileStream(finalFilePath, FileMode.Create)) + { + await image.SaveAsync(stream, encoder); + } + logger.Info($"图片压缩保存完成: {finalFilePath}"); } } + catch (Exception ex) + { + logger.Error(ex, $"图片压缩失败: {finalFilePath}, 错误: {ex.Message}"); + throw; + } } private async Task CompressImageAsync(IFormFile file, Stream outputStream, int quality) {