Commit addd9f4c79a923291d29cbc30b30003d8d5b62d1
1 parent
33599f59
feat: 配置annexpic接口使用阿里云OSS存储
- 创建annexpic_bak备份接口 - 配置阿里云OSS存储(成都区域) - annexpic接口强制使用阿里云OSS,不受全局FileStoreType配置影响 - 修复OSS路径格式问题(使用正斜杠) - 更新BucketName为lvqian-erip
Showing
3 changed files
with
74 additions
and
13 deletions
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": | ... | ... |