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 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 _logger; //private readonly IOssResourceRepository _ossResourceRepository; public OssService(IOptionsMonitor options, CSRedisClient redis, ILogger logger) { // _ossOption = configuration.GetSection("AliyunOSSConfigs").Get(); _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 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 { new { Action = new List { "oss:PutObject", "oss:GetObject","oss:DeleteObject" }, Resource = new List { $"acs:oss:*:*:{_ossOption.BucketName}/temp/*" }, //Condition = new //{ // NumericLessThanEquals = new Dictionary() // { // {"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(stsJson); } } public async Task> 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 { new { Action = new List { "oss:PutObject", "oss:GetObject","oss:DeleteObject" }, Resource = new List { $"acs:oss:*:*:{_ossOption.BucketName}/temp/*" }, //Condition = new //{ // NumericLessThanEquals = new Dictionary() // { // {"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 { {"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>(stsJson); } /// /// 上传单个 /// /// /// 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; //} } /// /// 删除单个 /// /// /// 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; } } /// /// 删除多个 /// /// /// public bool DeleteObjects(List? 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)); //AppException.ThrowIf(!del, "删除资源失败"); return result.Keys.Count() == keys.Count; } catch (OssException ex) { _logger.LogError(ex.Message + ex.StackTrace); return false; } } public List ListObjects(string prefix) { try { var keys = new List(); 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; } } /// /// 复制文件 /// /// /// /// public bool CopyObject(string sourceObject, string targetObject, long? id = null) { try { //var metadata = new ObjectMetadata(); // 设置自定义元数据。自定义元数据为键值对(Key-Value)的形式,例如Key为mk1,Value为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, //}); //AppException.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; } } } }