Commit addd9f4c79a923291d29cbc30b30003d8d5b62d1

Authored by “wangming”
1 parent 33599f59

feat: 配置annexpic接口使用阿里云OSS存储

- 创建annexpic_bak备份接口
- 配置阿里云OSS存储(成都区域)
- annexpic接口强制使用阿里云OSS,不受全局FileStoreType配置影响
- 修复OSS路径格式问题(使用正斜杠)
- 更新BucketName为lvqian-erip
netcore/src/Application/NCC.API.Core/Startup.cs
... ... @@ -106,6 +106,38 @@ namespace NCC.API.Core
106 106  
107 107 #endregion
108 108  
  109 + #region 阿里云OSS
  110 +
  111 + var aliyunOSSEndpoint = App.Configuration["NCC_App:AliyunOSS:Endpoint"];
  112 + var aliyunOSSAccessKey = App.Configuration["NCC_App:AliyunOSS:AccessKeyId"];
  113 + var aliyunOSSSecretKey = App.Configuration["NCC_App:AliyunOSS:AccessKeySecret"];
  114 + var aliyunOSSRegion = App.Configuration["NCC_App:AliyunOSS:Region"];
  115 + var bucketName = App.Configuration["NCC_App:BucketName"];
  116 +
  117 + if (!string.IsNullOrEmpty(aliyunOSSEndpoint) && !string.IsNullOrEmpty(aliyunOSSAccessKey) && !string.IsNullOrEmpty(aliyunOSSSecretKey))
  118 + {
  119 + services.AddOSSService("aliyun", option =>
  120 + {
  121 + option.Provider = OSSProvider.Aliyun;
  122 + // 阿里云OSS Endpoint格式:oss-{region}.aliyuncs.com
  123 + // 注意:不要包含bucket名称,只需要区域Endpoint
  124 + option.Endpoint = aliyunOSSEndpoint;
  125 + option.AccessKey = aliyunOSSAccessKey;
  126 + option.SecretKey = aliyunOSSSecretKey;
  127 + option.IsEnableHttps = true;
  128 + option.IsEnableCache = true;
  129 + // 对于OnceMi.AspNetCore.OSS,Region是可选的
  130 + // 但如果出现Endpoint不匹配错误,可能需要明确设置Region
  131 + // 成都区域的Region格式:cn-chengdu
  132 + if (!string.IsNullOrEmpty(aliyunOSSRegion))
  133 + {
  134 + option.Region = aliyunOSSRegion;
  135 + }
  136 + });
  137 + }
  138 +
  139 + #endregion
  140 +
109 141 #region 微信
110 142 services.AddSenparcGlobalServices(App.Configuration)//Senparc.CO2NET 全局注册
111 143 .AddSenparcWeixinServices(App.Configuration);//Senparc.Weixin 注册(如果使用Senparc.Weixin SDK则添加)
... ...
netcore/src/Application/NCC.API/appsettings.json
... ... @@ -33,7 +33,7 @@
33 33 "DBType": "MySql", //MySql;SqlServer;Oracle;PostgreSQL;Dm;Kdbndp;
34 34 //SqlServer
35 35 // "DefaultConnection": "Data Source=localhost;Initial Catalog={0};User ID=sqladmin;Password=P@ssw0rd;MultipleActiveResultSets=true"
36   - "DefaultConnection": "Database={0};Data Source=rm-bp19ohrgc6111ynzh1o.mysql.rds.aliyuncs.com;Port=3306;User Id=netteam;Password=netteam;Charset=utf8;TreatTinyAsBoolean=true;"
  36 + "DefaultConnection": "Database={0};Data Source=rm-2vccze142rc9a8f58bo.mysql.cn-chengdu.rds.aliyuncs.com;Port=3306;User Id=lvqiansql;Password=LvQ1@n!20251211;Charset=utf8;TreatTinyAsBoolean=true;"
37 37  
38 38 },
39 39 "SpecificationDocumentSettings": {
... ... @@ -204,9 +204,16 @@
204 204 "domainKey": "yozoHbiPMzu50374"
205 205 },
206 206 //Minio
207   - "BucketName": "NCCsoftoss",
  207 + "BucketName": "lvqian-erip",
208 208 //文件存储类型(本地:local,MinIo:minio,阿里云:aliyun-oss,腾讯云:tencent-cos)
209 209 "FileStoreType": "local",
  210 + //阿里云OSS配置
  211 + "AliyunOSS": {
  212 + "AccessKeyId": "LTAI5t6h4i95uapwzDwKfNxi",
  213 + "AccessKeySecret": "84dpUAlu2eoyFOIEhFGkZlIy45h0B6",
  214 + "Endpoint": "oss-cn-chengdu.aliyuncs.com",
  215 + "Region": "cn-chengdu"
  216 + },
210 217 //================== 系统错误邮件报告反馈相关 ============================== -->
211 218 //软件的错误报告
212 219 "ErrorReport": "false",
... ...
netcore/src/Modularity/System/NCC.System/Service/Common/FileService.cs
... ... @@ -64,7 +64,11 @@ namespace NCC.System.Service.Common
64 64 throw NCCException.Oh(ErrorCode.D1800);
65 65 var _filePath = GetPathByType(type);
66 66 var _fileName = DateTime.Now.ToString("yyyyMMdd") + "_" + YitIdHelper.NextId().ToString() + Path.GetExtension(file.FileName);
67   - await UploadFileByType(file, _filePath, _fileName);
  67 +
  68 + // annexpic 类型强制使用阿里云OSS存储
  69 + string forceStoreType = type == "annexpic" ? "aliyun-oss" : null;
  70 + await UploadFileByType(file, _filePath, _fileName, forceStoreType);
  71 +
68 72 return new { name = _fileName, url = string.Format("/api/File/Image/{0}/{1}", type, _fileName) };
69 73 }
70 74  
... ... @@ -79,7 +83,9 @@ namespace NCC.System.Service.Common
79 83 public async Task<IActionResult> GetImg(string type, string fileName)
80 84 {
81 85 var filePath = Path.Combine(GetPathByType(type), fileName.Replace("@", "."));
82   - return await DownloadFileByType(filePath, fileName);
  86 + // annexpic 类型强制使用阿里云OSS存储
  87 + string forceStoreType = type == "annexpic" ? "aliyun-oss" : null;
  88 + return await DownloadFileByType(filePath, fileName, forceStoreType);
83 89 //return new FileStreamResult(new FileStream(filePath, FileMode.Open), "application/octet-stream") { FileDownloadName = fileName };
84 90 }
85 91  
... ... @@ -181,7 +187,9 @@ namespace NCC.System.Service.Common
181 187 fileDownloadName = Path.GetFileName(filePath);
182 188 if (fileDownloadName.IsNullOrWhiteSpace())
183 189 fileDownloadName = fileName.Replace(GetPathByType(type), "");
184   - return await DownloadFileByType(filePath, fileDownloadName);
  190 + // annexpic 类型强制使用阿里云OSS存储
  191 + string forceStoreType = type == "annexpic" ? "aliyun-oss" : null;
  192 + return await DownloadFileByType(filePath, fileDownloadName, forceStoreType);
185 193 }
186 194 else
187 195 {
... ... @@ -198,15 +206,19 @@ namespace NCC.System.Service.Common
198 206 /// <param name="file"></param>
199 207 /// <param name="filePath"></param>
200 208 /// <param name="fileName"></param>
  209 + /// <param name="forceStoreType">强制使用指定的存储类型(如:aliyun-oss),如果为空则使用配置的存储类型</param>
201 210 /// <returns></returns>
202 211 [NonAction]
203   - public async Task UploadFileByType(IFormFile file, string filePath, string fileName)
  212 + public async Task UploadFileByType(IFormFile file, string filePath, string fileName, string forceStoreType = null)
204 213 {
205 214 try
206 215 {
207 216 var bucketName = KeyVariable.BucketName;
208   - var fileStoreType = KeyVariable.FileStoreType;
209   - var uploadPath = Path.Combine(filePath, fileName);
  217 + var fileStoreType = !string.IsNullOrEmpty(forceStoreType) ? forceStoreType : KeyVariable.FileStoreType;
  218 + // OSS路径使用正斜杠,不使用Path.Combine
  219 + var uploadPath = fileStoreType == "aliyun-oss" || fileStoreType == "tencent-cos" || fileStoreType == "minio"
  220 + ? $"{filePath.TrimEnd('/').TrimEnd('\\')}/{fileName}"
  221 + : Path.Combine(filePath, fileName);
210 222 var stream = file.OpenReadStream();
211 223 switch (fileStoreType)
212 224 {
... ... @@ -229,9 +241,16 @@ namespace NCC.System.Service.Common
229 241 break;
230 242 }
231 243 }
232   - catch (Exception)
  244 + catch (Exception ex)
233 245 {
234   - throw NCCException.Oh(ErrorCode.D8003);
  246 + // 记录详细错误信息以便调试
  247 + var errorMsg = $"文件上传失败: {ex.Message}";
  248 + if (ex.InnerException != null)
  249 + {
  250 + errorMsg += $", InnerException: {ex.InnerException.Message}";
  251 + }
  252 + // 抛出包含详细信息的异常
  253 + throw NCCException.Oh($"[D8003] {errorMsg}");
235 254 }
236 255 }
237 256  
... ... @@ -240,14 +259,15 @@ namespace NCC.System.Service.Common
240 259 /// </summary>
241 260 /// <param name="filePath"></param>
242 261 /// <param name="fileDownLoadName"></param>
  262 + /// <param name="forceStoreType">强制使用指定的存储类型(如:aliyun-oss),如果为空则使用配置的存储类型</param>
243 263 /// <returns></returns>
244 264 [NonAction]
245   - public async Task<FileStreamResult> DownloadFileByType(string filePath, string fileDownLoadName)
  265 + public async Task<FileStreamResult> DownloadFileByType(string filePath, string fileDownLoadName, string forceStoreType = null)
246 266 {
247 267 try
248 268 {
249 269 var bucketName = KeyVariable.BucketName;
250   - var fileStoreType = KeyVariable.FileStoreType;
  270 + var fileStoreType = !string.IsNullOrEmpty(forceStoreType) ? forceStoreType : KeyVariable.FileStoreType;
251 271 switch (fileStoreType)
252 272 {
253 273 case "minio":
... ... @@ -255,7 +275,7 @@ namespace NCC.System.Service.Common
255 275 var stream1 = await url1.GetAsStreamAsync();
256 276 return new FileStreamResult(stream1, "application/octet-stream") { FileDownloadName = fileDownLoadName };
257 277 case "aliyun-oss":
258   - var url2 = await _oSSServiceFactory.Create("Aliyun").PresignedGetObjectAsync(bucketName, filePath, 86400);
  278 + var url2 = await _oSSServiceFactory.Create("aliyun").PresignedGetObjectAsync(bucketName, filePath, 86400);
259 279 var stream2 = await url2.GetAsStreamAsync();
260 280 return new FileStreamResult(stream2, "application/octet-stream") { FileDownloadName = fileDownLoadName };
261 281 case "tencent-cos":
... ... @@ -299,6 +319,8 @@ namespace NCC.System.Service.Common
299 319 return FileVariable.SystemFilePath;
300 320 case "annexpic":
301 321 return FileVariable.SystemFilePath;
  322 + case "annexpic_bak":
  323 + return FileVariable.SystemFilePath;
302 324 case "document":
303 325 return FileVariable.DocumentFilePath;
304 326 case "diskdocument":
... ...