diff --git a/Infrastructure/Model/OptionsSetting.cs b/Infrastructure/Model/OptionsSetting.cs
index 4f9f552..5190665 100644
--- a/Infrastructure/Model/OptionsSetting.cs
+++ b/Infrastructure/Model/OptionsSetting.cs
@@ -32,6 +32,10 @@ namespace Infrastructure.Model
/// 阿里云oss
///
public ALIYUN_OSS ALIYUN_OSS { get; set; }
+ ///
+ /// 腾讯云COS
+ ///
+ public TENCENT_COS TENCENT_COS { get; set; }
public JwtSettings JwtSettings { get; set; }
///
/// 代码生成配置
@@ -86,6 +90,19 @@ namespace Infrastructure.Model
public int MaxSize { get; set; } = 100;
}
+ ///
+ /// 腾讯云COS存储
+ ///
+ public class TENCENT_COS
+ {
+ public string REGION { get; set; }
+ public string SECRET_ID { get; set; }
+ public string SECRET_KEY { get; set; }
+ public string BUCKET_NAME { get; set; }
+ public string DOMAIN_URL { get; set; }
+ public int MAX_SIZE { get; set; } = 100;
+ }
+
///
/// Jwt
///
diff --git a/ZR.Admin.WebApi/Controllers/CommonController.cs b/ZR.Admin.WebApi/Controllers/CommonController.cs
index d6dde76..2e39c71 100644
--- a/ZR.Admin.WebApi/Controllers/CommonController.cs
+++ b/ZR.Admin.WebApi/Controllers/CommonController.cs
@@ -98,7 +98,7 @@ namespace ZR.Admin.WebApi.Controllers
///
[HttpPost]
[ActionPermissionFilter(Permission = "common")]
- public async Task UploadFile([FromForm] UploadDto uploadDto, IFormFile file, StoreType storeType = StoreType.LOCAL)
+ public async Task UploadFile([FromForm] UploadDto uploadDto, IFormFile file, StoreType storeType = StoreType.TENCENT)
{
if (file == null) throw new CustomException(ResultCode.PARAM_ERROR, "上传文件不能为空");
SysFile sysfile = new();
@@ -152,6 +152,25 @@ namespace ZR.Admin.WebApi.Controllers
if (sysfile.Id <= 0) { return ToResponse(ApiResult.Error("阿里云连接失败")); }
break;
case StoreType.TENCENT:
+ int TencentMaxSize = OptionsSetting.TENCENT_COS.MAX_SIZE;
+ if (OptionsSetting.TENCENT_COS.REGION.IsEmpty())
+ {
+ return ToResponse(ResultCode.CUSTOM_ERROR, "配置文件缺失");
+ }
+ if ((fileSize / 1024) > TencentMaxSize)
+ {
+ return ToResponse(ResultCode.CUSTOM_ERROR, "上传文件过大,不能超过 " + TencentMaxSize + " MB");
+ }
+ sysfile = new(formFile.FileName, uploadDto.FileName, fileExt, fileSize + "kb", uploadDto.FileDir, HttpContext.GetName())
+ {
+ StoreType = (int)StoreType.TENCENT,
+ FileType = formFile.ContentType,
+ ClassifyType = uploadDto.ClassifyType,
+ CategoryId = uploadDto.CategoryId,
+ };
+ sysfile = await SysFileService.SaveFileToTencent(sysfile, uploadDto, formFile);
+
+ if (sysfile.Id <= 0) { return ToResponse(ApiResult.Error("腾讯云连接失败")); }
break;
case StoreType.QINIU:
break;
diff --git a/ZR.Admin.WebApi/appsettings.json b/ZR.Admin.WebApi/appsettings.json
index 996787d..b012ca5 100644
--- a/ZR.Admin.WebApi/appsettings.json
+++ b/ZR.Admin.WebApi/appsettings.json
@@ -45,7 +45,7 @@
"RefreshTokenTime": 30, //分钟
"TokenType": "Bearer"
},
- "MainDb": "0",// 多租户主库配置ID
+ "MainDb": "0", // 多租户主库配置ID
"UseTenant": 0, //是否启用多租户 0:不启用 1:启用
"InjectClass": [ "ZR.Repository", "ZR.Service", "ZR.Tasks", "ZR.ServiceCore", "ZR.Mall", "ZR.LiveForum" ], //自动注入类
"ShowDbLog": true, //是否打印db日志
@@ -70,6 +70,16 @@
"domainUrl": "http://xxx.xxx.com", //访问资源域名
"maxSize": 100 //上传文件大小限制 100M
},
+ //腾讯云COS存储配置
+ "TENCENT_COS": {
+ "APPID": "1308826010",
+ "REGION": "ap-shanghai", //eg:ap-beijing
+ "SECRET_ID": "AKIDVyMfzKZdZP8zkNyOdsFuSsBJDB7EScs0",
+ "SECRET_KEY": "89GWr7JPWYTL8ueHlAYowGZnvzKZjqs9",
+ "BUCKET_NAME": "miaoyu",
+ "DOMAIN_URL": "https://miaoyu-1308826010.cos.ap-shanghai.myqcloud.com", //访问资源域名
+ "MAX_SIZE": 100 //上传文件大小限制 100M
+ },
//企业微信通知配置
"WxCorp": {
"AgentID": "",
diff --git a/ZR.Common/TencentCosHelper.cs b/ZR.Common/TencentCosHelper.cs
new file mode 100644
index 0000000..33690dd
--- /dev/null
+++ b/ZR.Common/TencentCosHelper.cs
@@ -0,0 +1,110 @@
+using COSXML;
+using COSXML.Auth;
+using COSXML.Model.Object;
+
+using Infrastructure;
+
+using System;
+using System.IO;
+using System.Net;
+
+namespace ZR.Common
+{
+ public class TencentCosHelper
+ {
+ static string secretId = AppSettings.GetConfig("TENCENT_COS:SECRET_ID");
+ static string secretKey = AppSettings.GetConfig("TENCENT_COS:SECRET_KEY");
+ static string region = AppSettings.GetConfig("TENCENT_COS:REGION");
+ static string bucketName1 = AppSettings.GetConfig("TENCENT_COS:BUCKET_NAME");
+ static string appId = AppSettings.GetConfig("TENCENT_COS:APPID");
+
+
+ ///
+ /// 获取COS客户端
+ ///
+ ///
+ private static CosXmlServer GetCosXmlServer()
+ {
+ var config = new CosXmlConfig.Builder()
+ .SetRegion(region)
+ .Build();
+
+ var qCloudCredentialProvider = new DefaultQCloudCredentialProvider(secretId, secretKey, 600);
+ return new CosXmlServer(config, qCloudCredentialProvider);
+ }
+
+ ///
+ /// 上传到腾讯云COS
+ ///
+ /// 文件流
+ /// 存储路径 eg: upload/2020/01/01/xxx.png
+ /// 存储桶 如果为空默认取配置文件
+ ///
+ public static HttpStatusCode PutObjectFromFile(Stream filestreams, string dirPath, string bucketName = "")
+ {
+ if (string.IsNullOrEmpty(bucketName)) { bucketName = bucketName1; }
+ try
+ {
+ dirPath = dirPath.Replace("\\", "/");
+
+ var cosXml = GetCosXmlServer();
+
+ var request = new PutObjectRequest(bucketName, dirPath, filestreams);
+ request.APPID = appId;
+ var result = cosXml.PutObject(request);
+
+ return result.IsSuccessful() ? HttpStatusCode.OK : HttpStatusCode.BadRequest;
+ }
+ catch (COSXML.CosException.CosClientException ex)
+ {
+ Console.WriteLine("Failed with CosClientException: {0}", ex.Message);
+ }
+ catch (COSXML.CosException.CosServerException ex)
+ {
+ Console.WriteLine("Failed with CosServerException. ErrorCode: {0}; ErrorMessage: {1}; RequestID: {2}",
+ ex.errorCode, ex.Message, ex.requestId);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("Failed with error info: {0}", ex.Message);
+ }
+ return HttpStatusCode.BadRequest;
+ }
+
+ ///
+ /// 删除资源
+ ///
+ /// 文件路径
+ /// 存储桶 如果为空默认取配置文件
+ ///
+ public static HttpStatusCode DeleteFile(string dirPath, string bucketName = "")
+ {
+ if (string.IsNullOrEmpty(bucketName)) { bucketName = bucketName1; }
+ try
+ {
+ dirPath = dirPath.Replace("\\", "/");
+
+ var cosXml = GetCosXmlServer();
+ var request = new DeleteObjectRequest(bucketName, dirPath);
+ var result = cosXml.DeleteObject(request);
+
+ return result.IsSuccessful() ? HttpStatusCode.OK : HttpStatusCode.BadRequest;
+ }
+ catch (COSXML.CosException.CosClientException ex)
+ {
+ Console.WriteLine("Failed with CosClientException: {0}", ex.Message);
+ }
+ catch (COSXML.CosException.CosServerException ex)
+ {
+ Console.WriteLine("Failed with CosServerException. ErrorCode: {0}; ErrorMessage: {1}; RequestID: {2}",
+ ex.errorCode, ex.errorMessage, ex.requestId);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("Failed with error info: {0}", ex.Message);
+ }
+ return HttpStatusCode.BadRequest;
+ }
+ }
+}
+
diff --git a/ZR.Common/ZR.Common.csproj b/ZR.Common/ZR.Common.csproj
index bbef2da..79bfdc8 100644
--- a/ZR.Common/ZR.Common.csproj
+++ b/ZR.Common/ZR.Common.csproj
@@ -8,6 +8,8 @@
+
+
diff --git a/ZR.ServiceCore/Services/IService/ISysFileService.cs b/ZR.ServiceCore/Services/IService/ISysFileService.cs
index bd8be50..aeb88ab 100644
--- a/ZR.ServiceCore/Services/IService/ISysFileService.cs
+++ b/ZR.ServiceCore/Services/IService/ISysFileService.cs
@@ -31,6 +31,15 @@ namespace ZR.ServiceCore.Services
///
Task SaveFileToAliyun(SysFile file, UploadDto dto, IFormFile formFile);
+ ///
+ /// 上传文件到腾讯云
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task SaveFileToTencent(SysFile file, UploadDto dto, IFormFile formFile);
+
///
/// 按时间来创建文件夹
///
diff --git a/ZR.ServiceCore/Services/SysFileService.cs b/ZR.ServiceCore/Services/SysFileService.cs
index b8b39e6..755446e 100644
--- a/ZR.ServiceCore/Services/SysFileService.cs
+++ b/ZR.ServiceCore/Services/SysFileService.cs
@@ -133,6 +133,42 @@ namespace ZR.ServiceCore.Services
return file;
}
+ ///
+ /// 上传文件到腾讯云
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task SaveFileToTencent(SysFile file, UploadDto dto, IFormFile formFile)
+ {
+ string tencentDomainUrl = AppSettings.GetConfig("TENCENT_COS:DOMAIN_URL");
+ file.FileName = (file.FileName.IsEmpty() ? HashFileName() : file.FileName) + file.FileExt;
+ file.StorePath = GetdirPath(file.StorePath);
+ string finalPath = Path.Combine(file.StorePath, file.FileName);
+ HttpStatusCode statusCode;
+ if (dto.Quality > 0)
+ {
+ // 压缩图片
+ using var stream = new MemoryStream();
+ await CompressImageAsync(formFile, stream, dto.Quality);
+ stream.Position = 0;
+ statusCode = TencentCosHelper.PutObjectFromFile(stream, finalPath, "");
+ }
+ else
+ {
+ statusCode = TencentCosHelper.PutObjectFromFile(formFile.OpenReadStream(), finalPath, "");
+ }
+ if (statusCode != HttpStatusCode.OK) return file;
+
+ file.StorePath = file.StorePath;
+ file.FileUrl = finalPath;
+ file.AccessUrl = string.Concat(tencentDomainUrl, "/", file.StorePath.Replace("\\", "/"), "/", file.FileName);
+ file.Id = await InsertFile(file);
+
+ return file;
+ }
+
///
/// 获取文件存储目录
///