using COSXML;
using COSXML.Auth;
using COSXML.Model.Object;
using COSSTS;
using LiveForum.Code.Base;
using LiveForum.IService.Others;
using LiveForum.Model.Dto.Others;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using COSXML.Model.Tag;
namespace LiveForum.Service.Others
{
///
/// 腾讯云COS服务实现
///
public class CosService : ICosService
{
private readonly TencentCosConfig _config;
private readonly CosXml _cosXml;
private readonly CosXmlConfig _cosXmlConfig;
///
/// 构造函数
///
/// COS配置
public CosService(IOptions config)
{
_config = config.Value;
// 初始化COS配置
_cosXmlConfig = new CosXmlConfig.Builder()
.SetRegion(_config.Region)
.Build();
// 创建凭证提供者
var qCloudCredentialProvider = new DefaultQCloudCredentialProvider(
_config.SecretId,
_config.SecretKey,
_config.DurationSecond);
// 初始化COS客户端
_cosXml = new CosXmlServer(_cosXmlConfig, qCloudCredentialProvider);
}
///
/// 生成签名URL
///
/// 请求参数
/// 签名URL和过期时间
public async Task> GenerateSignURL(CosGenerateSignReq request)
{
try
{
var preSignatureStruct = new PreSignatureStruct
{
appid = _config.AppId,
region = _config.Region,
bucket = $"{_config.BucketName}-{_config.AppId}",
key = request.Key,
httpMethod = request.HttpMethod,
isHttps = request.IsHttps,
signDurationSecond = _config.DurationSecond,
headers = null,
queryParameters = null
};
// 生成预签名URL
string signUrl = _cosXml.GenerateSignURL(preSignatureStruct);
var response = new CosGenerateSignRespDto
{
SignUrl = signUrl,
ExpiredSeconds = (int)_config.DurationSecond
};
return new BaseResponse(response);
}
catch (COSXML.CosException.CosClientException clientEx)
{
return new BaseResponse(
ResponseCode.Error,
$"生成签名URL失败(客户端错误):{clientEx.Message}");
}
catch (COSXML.CosException.CosServerException serverEx)
{
return new BaseResponse(
ResponseCode.Error,
$"生成签名URL失败(服务器错误):{serverEx.GetInfo()}");
}
catch (Exception ex)
{
return new BaseResponse(
ResponseCode.Error,
$"生成签名URL失败:{ex.Message}");
}
}
///
/// 生成临时密钥
///
/// 请求参数
/// 临时密钥信息
public async Task> GenerateTemporaryKey(CosGenerateTemporaryKeyReq request)
{
try
{
// 验证和设置参数
string bucket = $"{_config.BucketName}-{_config.AppId}";
string region = _config.Region;
string prefixes = request.Prefixes ?? _config.Prefixes;
// 允许的路径前缀
string allowPrefix = "*";
// 密钥的权限列表
string[] allowActions = new string[]
{
"name/cos:PutObject",
"name/cos:PostObject",
"name/cos:InitiateMultipartUpload",
"name/cos:ListMultipartUploads",
"name/cos:ListParts",
"name/cos:UploadPart",
"name/cos:CompleteMultipartUpload"
};
// 设置参数
Dictionary values = new Dictionary();
values.Add("bucket", bucket);
values.Add("region", region);
values.Add("allowPrefix", allowPrefix);
values.Add("allowPrefixes", new string[] { string.IsNullOrEmpty(prefixes) ? "file/*" : $"{prefixes}/*" });
values.Add("allowActions", allowActions);
values.Add("durationSeconds", _config.DurationSecond);
values.Add("secretId", _config.SecretId);
values.Add("secretKey", _config.SecretKey);
// 生成临时凭证
Dictionary credential = STSClient.genCredential(values);
// 手动映射字段(因为STS返回的字段名可能与DTO不完全匹配)
var tempKeyEntity = new CosGenerateTemporaryKeyRespDto
{
Bucket = bucket,
Region = region,
Prefixes = prefixes
};
// 提取凭证信息
if (credential.TryGetValue("credentials", out var credsObj) && credsObj is Dictionary credsDict)
{
tempKeyEntity.Credentials = new CredentialsDto
{
Token = credsDict.TryGetValue("token", out var token) ? token?.ToString() ?? string.Empty : string.Empty,
TmpSecretId = credsDict.TryGetValue("tmpSecretId", out var tmpSecretId) ? tmpSecretId?.ToString() ?? string.Empty : string.Empty,
TmpSecretKey = credsDict.TryGetValue("tmpSecretKey", out var tmpSecretKey) ? tmpSecretKey?.ToString() ?? string.Empty : string.Empty
};
}
// 提取时间信息
if (credential.TryGetValue("expiration", out var expiration))
{
tempKeyEntity.Expiration = expiration?.ToString() ?? string.Empty;
}
if (credential.TryGetValue("expiredTime", out var expiredTime) && expiredTime != null)
{
if (long.TryParse(expiredTime.ToString(), out long expiredTimeLong))
{
tempKeyEntity.ExpiredTime = expiredTimeLong;
}
}
if (credential.TryGetValue("startTime", out var startTime) && startTime != null)
{
if (long.TryParse(startTime.ToString(), out long startTimeLong))
{
tempKeyEntity.StartTime = startTimeLong;
}
}
// 生成文件路径
string modelName = string.IsNullOrEmpty(request.ModelName) ? "images" : request.ModelName;
string fileName = request.FileName;
if (!string.IsNullOrEmpty(fileName))
{
var ext = System.IO.Path.GetExtension(fileName);
if (!string.IsNullOrEmpty(ext))
{
// 使用 UTC 时间生成时间戳文件名
fileName = $"{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}{ext}";
}
}
tempKeyEntity.FilePath = $"{prefixes}/{modelName}/{DateTime.Now:yyyyMMdd}/{fileName}";
tempKeyEntity.DomainName = _config.DomainUrl;
return new BaseResponse(tempKeyEntity);
}
catch (Exception ex)
{
return new BaseResponse(
ResponseCode.Error,
$"生成临时密钥失败:{ex.Message}");
}
}
}
}