fix: 修复COS上传图片损坏

This commit is contained in:
2025-12-15 13:25:04 +08:00
parent 9192ef3021
commit f2ec40a533

View File

@@ -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 />