internal virtual string BuildPresignedObjectCacheKey(string bucketName, string objectName, PresignedObjectType type)
 {
     return(Encrypt.MD5($"{this.GetType().FullName}_{bucketName}_{objectName}_{type.ToString().ToUpper()}"));
 }
        private async Task <string> PresignedObjectAsync(string bucketName, string objectName, int expiresInt, PresignedObjectType type)
        {
            if (string.IsNullOrEmpty(bucketName))
            {
                throw new ArgumentNullException(nameof(bucketName));
            }
            if (string.IsNullOrEmpty(objectName))
            {
                throw new ArgumentNullException(nameof(objectName));
            }
            if (expiresInt <= 0)
            {
                throw new Exception("ExpiresIn time can not less than 0.");
            }
            if (expiresInt > 7 * 24 * 3600)
            {
                throw new Exception("ExpiresIn time no more than 7 days.");
            }
            long      nowTime       = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
            const int minExpiresInt = 600;
            string    key           = Encrypt.MD5($"{bucketName}_{objectName}_{type.ToString().ToUpper()}");
            string    objectUrl     = null;

            //查找缓存
            if (Options.IsEnableCache && (expiresInt > minExpiresInt))
            {
                var cacheResult = await _cache.GetAsync <PresignedUrlCache>(key);

                PresignedUrlCache cache = cacheResult.HasValue ? cacheResult.Value : null;
                //缓存中存在,且有效时间不低于10分钟
                if (cache != null &&
                    cache.Type == type &&
                    cache.CreateTime > 0 &&
                    (cache.CreateTime + expiresInt - nowTime) > minExpiresInt &&
                    cache.Name == objectName &&
                    cache.BucketName == bucketName)
                {
                    return(cache.Url);
                }
            }
            if (type == PresignedObjectType.Get)
            {
                //生成URL
                AccessMode accessMode = await this.GetObjectAclAsync(bucketName, objectName);

                if (accessMode == AccessMode.PublicRead || accessMode == AccessMode.PublicReadWrite)
                {
                    string bucketUrl = await this.GetBucketEndpointAsync(bucketName);

                    objectUrl = $"{bucketUrl}{(objectName.StartsWith("/") ? "" : "/")}{objectName}";
                }
                else
                {
                    var req = new GeneratePresignedUriRequest(bucketName, objectName, SignHttpMethod.Get)
                    {
                        Expiration = DateTime.Now.AddSeconds(expiresInt)
                    };
                    var uri = _client.GeneratePresignedUri(req);
                    if (uri != null)
                    {
                        objectUrl = uri.ToString();
                    }
                }
            }
            else
            {
                var req = new GeneratePresignedUriRequest(bucketName, objectName, SignHttpMethod.Put)
                {
                    Expiration = DateTime.Now.AddSeconds(expiresInt)
                };
                var uri = _client.GeneratePresignedUri(req);
                if (uri != null)
                {
                    objectUrl = uri.ToString();
                }
            }
            if (string.IsNullOrEmpty(objectUrl))
            {
                throw new Exception("Presigned get object url failed.");
            }
            //save cache
            if (Options.IsEnableCache && expiresInt > minExpiresInt)
            {
                PresignedUrlCache urlCache = new PresignedUrlCache()
                {
                    Url        = objectUrl,
                    CreateTime = nowTime,
                    Name       = objectName,
                    BucketName = bucketName,
                    Type       = type
                };
                int randomSec = new Random().Next(5, 30);
                await _cache.SetAsync(key, urlCache, TimeSpan.FromSeconds(expiresInt + randomSec));
            }
            return(objectUrl);
        }
        private async Task <string> PresignedObjectAsync(string bucketName, string objectName, int expiresInt, PresignedObjectType type)
        {
            if (string.IsNullOrEmpty(bucketName))
            {
                throw new ArgumentNullException(nameof(bucketName));
            }
            if (string.IsNullOrEmpty(objectName))
            {
                throw new ArgumentNullException(nameof(objectName));
            }
            if (expiresInt <= 0)
            {
                throw new Exception("ExpiresIn time can not less than 0.");
            }
            if (expiresInt > 7 * 24 * 3600)
            {
                throw new Exception("ExpiresIn time no more than 7 days.");
            }
            long               nowTime            = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
            const int          minExpiresInt      = 600;
            string             key                = Encrypt.MD5($"{bucketName}_{objectName}_{type.ToString().ToUpper()}");
            string             objectUrl          = null;
            string             newBucketName      = ConvertBucketName(bucketName);
            PreSignatureStruct preSignatureStruct = new PreSignatureStruct()
            {
                appid              = Options.Endpoint,
                region             = Options.Region,
                bucket             = newBucketName,
                key                = objectName,
                httpMethod         = type.ToString().ToUpper(),
                isHttps            = Options.IsEnableHttps,
                signDurationSecond = expiresInt,
                headers            = null,
                queryParameters    = null,
            };

            //查找缓存
            if (Options.IsEnableCache && (expiresInt > minExpiresInt))
            {
                var cacheResult = await _cache.GetAsync <PresignedUrlCache>(key);

                PresignedUrlCache cache = cacheResult.HasValue ? cacheResult.Value : null;
                //缓存中存在,且有效时间不低于10分钟
                if (cache != null &&
                    cache.Type == type &&
                    cache.CreateTime > 0 &&
                    (cache.CreateTime + expiresInt - nowTime) > minExpiresInt &&
                    cache.Name == objectName &&
                    cache.BucketName == bucketName)
                {
                    return(cache.Url);
                }
            }
            if (type == PresignedObjectType.Get)
            {
                //生成URL
                AccessMode accessMode = await this.GetObjectAclAsync(bucketName, objectName);

                if (accessMode == AccessMode.PublicRead || accessMode == AccessMode.PublicReadWrite)
                {
                    objectUrl = $"{(Options.IsEnableHttps ? "https" : "http")}://{newBucketName}.cos.{Options.Region}.myqcloud.com{(objectName.StartsWith("/") ? "" : "/")}{objectName}";
                }
                else
                {
                    string uri = _client.GenerateSignURL(preSignatureStruct);
                    if (uri != null)
                    {
                        objectUrl = uri.ToString();
                    }
                }
            }
            else
            {
                string uri = _client.GenerateSignURL(preSignatureStruct);
                if (uri != null)
                {
                    objectUrl = uri.ToString();
                }
            }
            if (string.IsNullOrEmpty(objectUrl))
            {
                throw new Exception("Presigned get object url failed.");
            }
            //save cache
            if (Options.IsEnableCache && expiresInt > minExpiresInt)
            {
                PresignedUrlCache urlCache = new PresignedUrlCache()
                {
                    Url        = objectUrl,
                    CreateTime = nowTime,
                    Name       = objectName,
                    BucketName = bucketName,
                    Type       = type
                };
                int randomSec = new Random().Next(5, 30);
                await _cache.SetAsync(key, urlCache, TimeSpan.FromSeconds(expiresInt + randomSec));
            }
            return(objectUrl);
        }