namespace Tiku.Application.Storage; public static class ObjectStorageProviders { public const string ExternalUrl = "external_url"; public const string AliyunOss = "aliyun_oss"; public const string TencentCos = "tencent_cos"; public const string QiniuKodo = "qiniu_kodo"; public const string LocalDev = "local_dev"; } public sealed record StorageAssetLocation( string Provider, string? Bucket, string? ObjectKey, string? CdnUrl = null); public sealed record ObjectStorageUploadSignRequest( Guid TenantId, string Provider, string Bucket, string ObjectKey, string FileName, string MimeType, long? FileSizeBytes, TimeSpan ExpiresIn, bool Upsert = false); public sealed record ObjectStorageDownloadSignRequest( Guid TenantId, string Provider, string? Bucket, string? ObjectKey, TimeSpan ExpiresIn, string? CdnUrl = null, string? FileName = null, string Disposition = "attachment"); public sealed record ObjectStorageHeadRequest( Guid TenantId, string Provider, string? Bucket, string? ObjectKey, string? DeclaredMimeType = null, long? DeclaredFileSizeBytes = null, string? DeclaredChecksumSha256 = null); public sealed record ObjectStorageReadRequest( Guid TenantId, string Provider, string Bucket, string ObjectKey); public sealed record ObjectStorageWriteRequest( Guid TenantId, string Provider, string Bucket, string ObjectKey, string MimeType, Stream Content, long? FileSizeBytes, string? ChecksumSha256 = null, IReadOnlyDictionary? Metadata = null, bool Upsert = true); public sealed record ObjectStorageSignedUrl( string Provider, string? Bucket, string? ObjectKey, string Method, Uri Url, IReadOnlyDictionary Headers, DateTimeOffset ExpiresAt, TimeSpan ExpiresIn, string SignatureMode); public sealed record ObjectStorageMetadata( string Provider, string? Bucket, string? ObjectKey, bool Exists, long? SizeBytes, string? MimeType, string? ChecksumSha256, string? ETag, string? LastModified, IReadOnlyDictionary RawHeaders, string VerificationSource); public sealed record ObjectStorageWriteResult( string Provider, string Bucket, string ObjectKey, Uri? PublicUrl, long? SizeBytes, string? MimeType, string? ChecksumSha256, string? ETag, IReadOnlyDictionary RawHeaders, string VerificationSource); public class ObjectStorageException(string message, string code) : InvalidOperationException(message) { public string Code { get; } = code; } public sealed class ObjectStorageNotConfiguredException(string message) : ObjectStorageException(message, "STORAGE_PROVIDER_NOT_CONFIGURED");