fix: 修复COS上传图片损坏
This commit is contained in:
@@ -60,6 +60,12 @@ public abstract class S3StorageProviderBase : IObjectStorageProvider, IDisposabl
|
||||
/// <inheritdoc />
|
||||
public virtual async Task<StorageUploadResult> UploadAsync(StorageUploadRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
// 0. 兜底重置流位置,避免上游读取导致内容缺失
|
||||
if (request.Content.CanSeek)
|
||||
{
|
||||
request.Content.Position = 0;
|
||||
}
|
||||
|
||||
// 1. 构建上传请求
|
||||
var putRequest = new PutObjectRequest
|
||||
{
|
||||
@@ -67,9 +73,18 @@ public abstract class S3StorageProviderBase : IObjectStorageProvider, IDisposabl
|
||||
Key = request.ObjectKey,
|
||||
InputStream = request.Content,
|
||||
AutoCloseStream = false,
|
||||
ContentType = request.ContentType
|
||||
ContentType = request.ContentType,
|
||||
DisableDefaultChecksumValidation = true,
|
||||
UseChunkEncoding = false,
|
||||
DisablePayloadSigning = true
|
||||
};
|
||||
|
||||
// 1.1 显式设置 Content-Length,避免 S3 SDK 对兼容网关使用 aws-chunked 导致对象内容被写入“chunk-signature”头而损坏
|
||||
if (request.ContentLength > 0)
|
||||
{
|
||||
putRequest.Headers.ContentLength = request.ContentLength;
|
||||
}
|
||||
|
||||
foreach (var kv in request.Metadata)
|
||||
{
|
||||
putRequest.Metadata[kv.Key] = kv.Value;
|
||||
@@ -167,17 +182,50 @@ public abstract class S3StorageProviderBase : IObjectStorageProvider, IDisposabl
|
||||
/// </summary>
|
||||
protected virtual IAmazonS3 CreateClient()
|
||||
{
|
||||
// 1. 尽量推断鉴权 Region(腾讯云 COS 的 S3 兼容域名形如:cos.ap-beijing.myqcloud.com)
|
||||
var authenticationRegion = ResolveAuthenticationRegion(ServiceUrl);
|
||||
|
||||
// 2. 构建客户端配置
|
||||
var config = new AmazonS3Config
|
||||
{
|
||||
ServiceURL = ServiceUrl,
|
||||
ForcePathStyle = ForcePathStyle,
|
||||
UseHttp = !UseHttps
|
||||
UseHttp = !UseHttps,
|
||||
AuthenticationRegion = authenticationRegion
|
||||
};
|
||||
|
||||
// 3. 创建客户端并返回
|
||||
var credentials = new BasicAWSCredentials(AccessKey, SecretKey);
|
||||
return new AmazonS3Client(credentials, config);
|
||||
}
|
||||
|
||||
private static string? ResolveAuthenticationRegion(string serviceUrl)
|
||||
{
|
||||
// 1. 解析 URL
|
||||
if (!Uri.TryCreate(serviceUrl, UriKind.Absolute, out var uri))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// 2. 提取 Host
|
||||
var host = uri.Host;
|
||||
if (string.IsNullOrWhiteSpace(host))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// 3. 按 COS 域名规则解析 Region
|
||||
const string cosPrefix = "cos.";
|
||||
const string cosSuffix = ".myqcloud.com";
|
||||
if (host.StartsWith(cosPrefix, StringComparison.OrdinalIgnoreCase) &&
|
||||
host.EndsWith(cosSuffix, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var regionPart = host.Substring(cosPrefix.Length, host.Length - cosPrefix.Length - cosSuffix.Length);
|
||||
return string.IsNullOrWhiteSpace(regionPart) ? null : regionPart;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private IAmazonS3 Client => _client ??= CreateClient();
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
Reference in New Issue
Block a user