200 lines
6.7 KiB
C#
200 lines
6.7 KiB
C#
using COSXML;
|
||
using COSXML.Auth;
|
||
using COSXML.Model;
|
||
using COSXML.Model.Object;
|
||
using Infrastructure;
|
||
using Infrastructure.Model;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using ZR.Model.Business.Dto;
|
||
|
||
namespace ZR.Common
|
||
{
|
||
/// <summary>
|
||
/// 腾讯云COS服务
|
||
/// </summary>
|
||
public class CosService
|
||
{
|
||
private static readonly TencentCOS _config;
|
||
private static readonly CosXml _cosXml;
|
||
private static readonly string _bucket;
|
||
|
||
static CosService()
|
||
{
|
||
_config = AppSettings.Get<TencentCOS>("TencentCOS") ?? new TencentCOS();
|
||
_bucket = $"{_config.BucketName}-{_config.AppId}";
|
||
|
||
// 初始化COS客户端
|
||
var cosConfig = new CosXmlConfig.Builder()
|
||
.IsHttps(true)
|
||
.SetRegion(_config.Region)
|
||
.SetDebugLog(false)
|
||
.Build();
|
||
|
||
var qCloudCredentialProvider = new DefaultQCloudCredentialProvider(
|
||
_config.SecretId,
|
||
_config.SecretKey,
|
||
_config.DurationSecond);
|
||
|
||
_cosXml = new CosXmlServer(cosConfig, qCloudCredentialProvider);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成批量上传预签名URL
|
||
/// </summary>
|
||
/// <param name="request">上传请求参数</param>
|
||
/// <returns>预签名URL列表</returns>
|
||
public static CosUploadUrlsResponse GetUploadUrls(CosUploadUrlsRequest request)
|
||
{
|
||
var response = new CosUploadUrlsResponse
|
||
{
|
||
Images = new List<CosImageUploadInfo>()
|
||
};
|
||
|
||
var recordTime = request.RecordTime;
|
||
var dateFolder = recordTime.ToString("yyyyMM");
|
||
var dayFolder = recordTime.ToString("yyyyMMdd");
|
||
var timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds();
|
||
|
||
for (int i = 0; i < request.ImageCount; i++)
|
||
{
|
||
var random = new Random().Next(1000, 9999);
|
||
var fileName = $"{timestamp}_{random}{i}{request.FileExt}";
|
||
var imageId = Guid.NewGuid().ToString("N");
|
||
|
||
var imageInfo = new CosImageUploadInfo
|
||
{
|
||
ImageId = imageId,
|
||
FileName = fileName,
|
||
UploadUrls = new CosUploadUrls
|
||
{
|
||
Workers = new Dictionary<string, string>()
|
||
}
|
||
};
|
||
|
||
// 生成各分类目录的预签名URL
|
||
var basePath = $"{_config.Prefixes}/{dateFolder}/{dayFolder}";
|
||
|
||
// 1. 当日照片目录
|
||
var dailyPath = $"{basePath}/当日照片/{fileName}";
|
||
imageInfo.UploadUrls.Daily = GeneratePresignedUrl(dailyPath);
|
||
|
||
// 2. 参与人员目录(每个人员一个URL)
|
||
if (request.Workers != null)
|
||
{
|
||
foreach (var worker in request.Workers)
|
||
{
|
||
if (!string.IsNullOrWhiteSpace(worker))
|
||
{
|
||
var workerPath = $"{basePath}/参与人员/{worker}/{fileName}";
|
||
imageInfo.UploadUrls.Workers[worker] = GeneratePresignedUrl(workerPath);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 3. 工作内容目录
|
||
if (!string.IsNullOrWhiteSpace(request.Content))
|
||
{
|
||
var contentPath = $"{basePath}/工作内容/{request.Content}/{fileName}";
|
||
imageInfo.UploadUrls.Content = GeneratePresignedUrl(contentPath);
|
||
}
|
||
|
||
// 4. 部门目录
|
||
if (!string.IsNullOrWhiteSpace(request.DeptName))
|
||
{
|
||
var deptPath = $"{basePath}/部门/{request.DeptName}/{fileName}";
|
||
imageInfo.UploadUrls.Dept = GeneratePresignedUrl(deptPath);
|
||
}
|
||
|
||
// 设置访问URL(使用当日照片目录作为主URL)
|
||
imageInfo.AccessUrl = $"{_config.DomainUrl}/{dailyPath}";
|
||
|
||
response.Images.Add(imageInfo);
|
||
}
|
||
|
||
return response;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取临时密钥(用于迁移)
|
||
/// </summary>
|
||
/// <returns>临时密钥信息</returns>
|
||
public static CosTempCredentials GetTempCredentials()
|
||
{
|
||
// 返回配置中的密钥信息(实际生产环境应使用STS临时密钥)
|
||
return new CosTempCredentials
|
||
{
|
||
SecretId = _config.SecretId,
|
||
SecretKey = _config.SecretKey,
|
||
Region = _config.Region,
|
||
Bucket = _bucket,
|
||
DomainUrl = _config.DomainUrl,
|
||
Prefixes = _config.Prefixes,
|
||
DurationSecond = _config.DurationSecond
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成预签名URL
|
||
/// </summary>
|
||
/// <param name="key">对象键</param>
|
||
/// <returns>预签名URL</returns>
|
||
private static string GeneratePresignedUrl(string key)
|
||
{
|
||
try
|
||
{
|
||
// 使用PutObjectRequest生成预签名URL
|
||
var request = new PutObjectRequest(_bucket, key, new byte[0]);
|
||
var preSignatureStruct = new COSXML.Model.Tag.PreSignatureStruct
|
||
{
|
||
appid = _config.AppId,
|
||
region = _config.Region,
|
||
bucket = _bucket,
|
||
key = key,
|
||
httpMethod = "PUT",
|
||
isHttps = true,
|
||
signDurationSecond = _config.DurationSecond
|
||
};
|
||
|
||
return _cosXml.GenerateSignURL(preSignatureStruct);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"生成预签名URL失败: {ex.Message}");
|
||
return string.Empty;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证是否为有效的COS URL
|
||
/// </summary>
|
||
/// <param name="url">URL地址</param>
|
||
/// <returns>是否有效</returns>
|
||
public static bool IsValidCosUrl(string url)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(url))
|
||
return false;
|
||
|
||
return url.StartsWith(_config.DomainUrl + "/" + _config.Prefixes + "/");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取COS域名
|
||
/// </summary>
|
||
/// <returns>COS域名</returns>
|
||
public static string GetDomainUrl()
|
||
{
|
||
return _config.DomainUrl;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取路径前缀
|
||
/// </summary>
|
||
/// <returns>路径前缀</returns>
|
||
public static string GetPrefixes()
|
||
{
|
||
return _config.Prefixes;
|
||
}
|
||
}
|
||
}
|