fix: 修复COS上传图片损坏
This commit is contained in:
@@ -60,6 +60,12 @@ public abstract class S3StorageProviderBase : IObjectStorageProvider, IDisposabl
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual async Task<StorageUploadResult> UploadAsync(StorageUploadRequest request, CancellationToken cancellationToken = default)
|
public virtual async Task<StorageUploadResult> UploadAsync(StorageUploadRequest request, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
|
// 0. 兜底重置流位置,避免上游读取导致内容缺失
|
||||||
|
if (request.Content.CanSeek)
|
||||||
|
{
|
||||||
|
request.Content.Position = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// 1. 构建上传请求
|
// 1. 构建上传请求
|
||||||
var putRequest = new PutObjectRequest
|
var putRequest = new PutObjectRequest
|
||||||
{
|
{
|
||||||
@@ -67,9 +73,18 @@ public abstract class S3StorageProviderBase : IObjectStorageProvider, IDisposabl
|
|||||||
Key = request.ObjectKey,
|
Key = request.ObjectKey,
|
||||||
InputStream = request.Content,
|
InputStream = request.Content,
|
||||||
AutoCloseStream = false,
|
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)
|
foreach (var kv in request.Metadata)
|
||||||
{
|
{
|
||||||
putRequest.Metadata[kv.Key] = kv.Value;
|
putRequest.Metadata[kv.Key] = kv.Value;
|
||||||
@@ -167,17 +182,50 @@ public abstract class S3StorageProviderBase : IObjectStorageProvider, IDisposabl
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual IAmazonS3 CreateClient()
|
protected virtual IAmazonS3 CreateClient()
|
||||||
{
|
{
|
||||||
|
// 1. 尽量推断鉴权 Region(腾讯云 COS 的 S3 兼容域名形如:cos.ap-beijing.myqcloud.com)
|
||||||
|
var authenticationRegion = ResolveAuthenticationRegion(ServiceUrl);
|
||||||
|
|
||||||
|
// 2. 构建客户端配置
|
||||||
var config = new AmazonS3Config
|
var config = new AmazonS3Config
|
||||||
{
|
{
|
||||||
ServiceURL = ServiceUrl,
|
ServiceURL = ServiceUrl,
|
||||||
ForcePathStyle = ForcePathStyle,
|
ForcePathStyle = ForcePathStyle,
|
||||||
UseHttp = !UseHttps
|
UseHttp = !UseHttps,
|
||||||
|
AuthenticationRegion = authenticationRegion
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 3. 创建客户端并返回
|
||||||
var credentials = new BasicAWSCredentials(AccessKey, SecretKey);
|
var credentials = new BasicAWSCredentials(AccessKey, SecretKey);
|
||||||
return new AmazonS3Client(credentials, config);
|
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();
|
private IAmazonS3 Client => _client ??= CreateClient();
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
Reference in New Issue
Block a user