Files

357 lines
13 KiB
C#
Raw Permalink Normal View History

using Aliyun.Acs.Core;
using Aliyun.Acs.Core.Auth.Sts;
using Aliyun.Acs.Core.Profile;
using Aliyun.OSS;
using Aliyun.OSS.Common;
using CSRedis;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using QYZH.InteractiveMagazine.Common.Extensions;
using QYZH.InteractiveMagazine.Models.Common;
using QYZH.InteractiveMagazine.Models.Dto;
using System.Text.Json;
using System.Web;
namespace QYZH.InteractiveMagazine.Infrastructure.OSS
{
public class OssService
{
private readonly OssClient _ossClient;
private readonly OSSOptions _ossOption;
private readonly CSRedisClient _redis;
private readonly ILogger<OssService> _logger;
//private readonly IOssResourceRepository _ossResourceRepository;
public OssService(IOptionsMonitor<OSSOptions> options, CSRedisClient redis, ILogger<OssService> logger)
{
// _ossOption = configuration.GetSection("AliyunOSSConfigs").Get<OSSOptions>();
_ossOption = options.CurrentValue;
_ossClient = new OssClient($"oss-cn-{_ossOption.Region}.aliyuncs.com", _ossOption.AccessKeyID, _ossOption.AccessKeySecret);
_ossClient.SetRegion($"cn-{_ossOption.Region}");
_redis = redis;
_logger = logger;
//_ossResourceRepository = ossResourceRepository;
}
public async Task<OssCredentials> GetSTSTokenAsync(CancellationToken cancellationToken)
{
var stsJson = await _redis.GetAsync("STS-InteractiveMagazine-OssCredentials");
if (string.IsNullOrWhiteSpace(stsJson))
{
// ststoken
IClientProfile profile = DefaultProfile.GetProfile($"oss-cn-{_ossOption.Region}", _ossOption.AccessKeyID, _ossOption.AccessKeySecret);
DefaultAcsClient client = new DefaultAcsClient(profile);
var policy = new
{
Version = "1",
Statement = new List<dynamic>
{
new
{
Action = new List<string> { "oss:PutObject", "oss:GetObject","oss:DeleteObject" },
Resource = new List<string> { $"acs:oss:*:*:{_ossOption.BucketName}/temp/*" },
//Condition = new
//{
// NumericLessThanEquals = new Dictionary<string, object>()
// {
// {"oss:ContentLength",104857600 }
// }
//},
Effect = "Allow",
}
}
};
var assumeRoleRequest = new AssumeRoleRequest();
assumeRoleRequest.Policy = JsonSerializer.Serialize(policy);
assumeRoleRequest.RoleArn = _ossOption.RoleArn;
assumeRoleRequest.RoleSessionName = "oss-services";//这里的名字随便写
assumeRoleRequest.DurationSeconds = 3600;//过期时间
var response = client.GetAcsResponse(assumeRoleRequest);
var expiration = DateTime.Parse(response.Credentials.Expiration).AddMinutes(5);
var result = new OssCredentials
{
AccessKeyId = response.Credentials.AccessKeyId,
AccessKeySecret = response.Credentials.AccessKeySecret,
SecurityToken = response.Credentials.SecurityToken,
ExpireTime = expiration.ToMillisecondsTimestamp(),
BucketName = _ossOption.BucketName,
Region = $"oss-cn-{_ossOption.Region}",
Domain = _ossOption.Domain
};
await _redis.SetAsync("STS-InteractiveMagazine-OssCredentials", result, expiration - DateTime.Now);
return result;
}
else
{
return JsonSerializer.Deserialize<OssCredentials>(stsJson);
}
}
public async Task<Dictionary<string, string>> GetSTSToken()
{
var stsJson = await _redis.GetAsync("QYZH.InteractiveMagazine.STS");
if (stsJson.IsNull())
{
// ststoken
IClientProfile profile = DefaultProfile.GetProfile($"oss-cn-{_ossOption.Region}", _ossOption.AccessKeyID, _ossOption.AccessKeySecret);
DefaultAcsClient client = new DefaultAcsClient(profile);
var policy = new
{
Version = "1",
Statement = new List<dynamic>
{
new
{
Action = new List<string> { "oss:PutObject", "oss:GetObject","oss:DeleteObject" },
Resource = new List<string> { $"acs:oss:*:*:{_ossOption.BucketName}/temp/*" },
//Condition = new
//{
// NumericLessThanEquals = new Dictionary<string, object>()
// {
// {"oss:ContentLength",104857600 }
// }
//},
Effect = "Allow",
}
}
};
var request = new AssumeRoleRequest();
request.Policy = JsonSerializer.Serialize(policy);
request.RoleArn = _ossOption.RoleArn;
request.RoleSessionName = "oss-services";//这里的名字随便写
request.DurationSeconds = 3600;//过期时间
var response = client.GetAcsResponse(request);
var expiration = DateTime.Parse(response.Credentials.Expiration);
var result = new Dictionary<string, string>
{
{"AccessKeyId", response.Credentials.AccessKeyId},
{"AccessKeySecret",response.Credentials.AccessKeySecret },
{"SecurityToken",response.Credentials.SecurityToken },
{"Expiration", DateTime.Parse(response.Credentials.Expiration).ToString("yyyy-MM-dd HH:mm:ss") },
{"BucketName",_ossOption.BucketName },
{"Region",$"oss-cn-{_ossOption.Region }"},
{"Domain",_ossOption.Domain }
};
var seconds = (expiration - DateTime.Now).TotalSeconds - 300;
await _redis.SetAsync("QYZH.InteractiveMagazine.STS", result, TimeSpan.FromSeconds(seconds));
return result;
}
return JsonSerializer.Deserialize<Dictionary<string, string>>(stsJson);
}
/// <summary>
/// 上传单个
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public string PutObject(string key, Stream content)
{
//try
//{
var result = _ossClient.PutObject(_ossOption.BucketName, key, content);
if (result.HttpStatusCode == System.Net.HttpStatusCode.OK)
{
return key;
}
else return null;
//}
//catch (Exception ex)
//{
// return null;
//}
}
/// <summary>
/// 删除单个
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public bool DeleteObject(string key)
{
try
{
if (key.IsNull()) return false;
key = HttpUtility.UrlDecode(key);
//_ossResourceRepository.UpdateDiy.Set(s => s.Status, -1).Where(w => w.Path == key).ExecuteAffrows();
var result = _ossClient.DeleteObject(_ossOption.BucketName, key);
return result.HttpStatusCode == System.Net.HttpStatusCode.OK;
}
catch (OssException ex)
{
_logger.LogError(ex.Message + ex.StackTrace);
return false;
}
}
/// <summary>
/// 判断对象是否存在
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public bool DoesObjectExist(string key)
{
try
{
if (key.IsNull()) return false;
key = key.RemoveDomain();
key = HttpUtility.UrlDecode(key);
return _ossClient.DoesObjectExist(_ossOption.BucketName, key);
}
catch (OssException ex)
{
_logger.LogError(ex.Message + ex.StackTrace);
return false;
}
}
/// <summary>
/// 获取对象内容流
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public Stream? GetObjectStream(string key)
{
try
{
if (key.IsNull()) return null;
key = key.RemoveDomain();
key = HttpUtility.UrlDecode(key);
var ossObject = _ossClient.GetObject(_ossOption.BucketName, key);
return ossObject.Content;
}
catch (OssException ex)
{
_logger.LogError(ex.Message + ex.StackTrace);
return null;
}
}
/// <summary>
/// 删除多个
/// </summary>
/// <param name="keys"></param>
/// <returns></returns>
public bool DeleteObjects(List<string>? keys)
{
try
{
if (keys.IsNull()) return false;
// 设置为详细模式,返回所有删除的文件列表。
var quietMode = false;
keys = keys.Select(it => it.RemoveDomain()).ToList();
//_ossResourceRepository.UpdateDiy.Set(s => s.Status, -1).Where(w => keys.Contains(w.Path)).ExecuteAffrows();
var request = new DeleteObjectsRequest(_ossOption.BucketName, keys, quietMode);
// 删除多个文件。
var result = _ossClient.DeleteObjects(request);
//var del = _ossResourceRepository.Delete(w => keys.Contains(w.Path));
//BusinessException.ThrowIf(!del, "删除资源失败");
return result.Keys.Count() == keys.Count;
}
catch (OssException ex)
{
_logger.LogError(ex.Message + ex.StackTrace);
return false;
}
}
public List<string> ListObjects(string prefix)
{
try
{
var keys = new List<string>();
ObjectListing result = null;
string nextMarker = string.Empty;
do
{
var listObjectsRequest = new ListObjectsRequest(_ossOption.BucketName)
{
Marker = nextMarker,
MaxKeys = 100,
Prefix = prefix,
};
result = _ossClient.ListObjects(listObjectsRequest);
foreach (var summary in result.ObjectSummaries)
{
keys.Add(summary.Key);
}
nextMarker = result.NextMarker;
} while (result.IsTruncated);
return keys;
}
catch (OssException ex)
{
_logger.LogError(ex.Message + ex.StackTrace);
return null;
}
}
/// <summary>
/// 复制文件
/// </summary>
/// <param name="sourceObject"></param>
/// <param name="targetObject"></param>
/// <returns></returns>
public bool CopyObject(string sourceObject, string targetObject, long? id = null)
{
try
{
//var metadata = new ObjectMetadata();
// 设置自定义元数据。自定义元数据为键值对Key-Value的形式例如Key为mk1Value为mv1。
//metadata.AddHeader("mk1", "mv1");
//metadata.AddHeader("mk2", "mv2");
sourceObject = sourceObject.RemoveDomain();
sourceObject = Uri.UnescapeDataString(sourceObject);
//var uow = _unitOfWorkManager.Begin();
//var data = _ossResourceRepository.Insert(new OssResource
//{
// MainId = id,
// SoucePath = sourceObject,
// Path = targetObject,
//});
//BusinessException.ThrowIf(data.IsNull(), "资源添加失败");
var req = new CopyObjectRequest(_ossOption.BucketName, sourceObject, _ossOption.BucketName, targetObject)
{
// 如果NewObjectMetadata为null则为COPY模式即拷贝源文件的元数据非null则为REPLACE模式覆盖源文件的元数据
NewObjectMetadata = null
};
var result = _ossClient.CopyObject(req);
return result.HttpStatusCode == System.Net.HttpStatusCode.OK;
}
catch (OssException ex)
{
_logger.LogError(ex.Message + ex.StackTrace);
return false;
}
}
}
}