diff --git a/framework/src/Volo.Abp.BlobStoring.Aws/Volo/Abp/BlobStoring/Aws/AwsBlobProviderConfiguration.cs b/framework/src/Volo.Abp.BlobStoring.Aws/Volo/Abp/BlobStoring/Aws/AwsBlobProviderConfiguration.cs
index 1b31d176c8..77919b80ef 100644
--- a/framework/src/Volo.Abp.BlobStoring.Aws/Volo/Abp/BlobStoring/Aws/AwsBlobProviderConfiguration.cs
+++ b/framework/src/Volo.Abp.BlobStoring.Aws/Volo/Abp/BlobStoring/Aws/AwsBlobProviderConfiguration.cs
@@ -62,6 +62,15 @@ public class AwsBlobProviderConfiguration
set => _containerConfiguration.SetConfiguration(AwsBlobProviderConfigurationNames.Region, Check.NotNull(value, nameof(value)));
}
+ ///
+ /// Custom service URL for S3-compatible APIs (e.g., MinIO, DigitalOcean Spaces).
+ /// If not specified, the default AWS S3 service URL will be used based on the region.
+ ///
+ public string? ServiceURL {
+ get => _containerConfiguration.GetConfigurationOrDefault(AwsBlobProviderConfigurationNames.ServiceURL);
+ set => _containerConfiguration.SetConfiguration(AwsBlobProviderConfigurationNames.ServiceURL, value);
+ }
+
///
/// This name may only contain lowercase letters, numbers, and hyphens, and must begin with a letter or a number.
/// Each hyphen must be preceded and followed by a non-hyphen character.
diff --git a/framework/src/Volo.Abp.BlobStoring.Aws/Volo/Abp/BlobStoring/Aws/AwsBlobProviderConfigurationNames.cs b/framework/src/Volo.Abp.BlobStoring.Aws/Volo/Abp/BlobStoring/Aws/AwsBlobProviderConfigurationNames.cs
index d1b775c812..b065441462 100644
--- a/framework/src/Volo.Abp.BlobStoring.Aws/Volo/Abp/BlobStoring/Aws/AwsBlobProviderConfigurationNames.cs
+++ b/framework/src/Volo.Abp.BlobStoring.Aws/Volo/Abp/BlobStoring/Aws/AwsBlobProviderConfigurationNames.cs
@@ -14,6 +14,7 @@ public static class AwsBlobProviderConfigurationNames
public const string Name = "Aws.Name";
public const string Policy = "Aws.Policy";
public const string Region = "Aws.Region";
+ public const string ServiceURL = "Aws.ServiceURL";
public const string ContainerName = "Aws.ContainerName";
public const string CreateContainerIfNotExists = "Aws.CreateContainerIfNotExists";
}
diff --git a/framework/src/Volo.Abp.BlobStoring.Aws/Volo/Abp/BlobStoring/Aws/DefaultAmazonS3ClientFactory.cs b/framework/src/Volo.Abp.BlobStoring.Aws/Volo/Abp/BlobStoring/Aws/DefaultAmazonS3ClientFactory.cs
index dee0bf5096..dc2a7fe56b 100644
--- a/framework/src/Volo.Abp.BlobStoring.Aws/Volo/Abp/BlobStoring/Aws/DefaultAmazonS3ClientFactory.cs
+++ b/framework/src/Volo.Abp.BlobStoring.Aws/Volo/Abp/BlobStoring/Aws/DefaultAmazonS3ClientFactory.cs
@@ -31,30 +31,47 @@ public class DefaultAmazonS3ClientFactory : IAmazonS3ClientFactory, ITransientDe
AwsBlobProviderConfiguration configuration)
{
var region = RegionEndpoint.GetBySystemName(configuration.Region);
+ var clientConfig = CreateS3ClientConfig(configuration, region);
if (configuration.UseCredentials)
{
var awsCredentials = GetAwsCredentials(configuration);
return awsCredentials == null
- ? new AmazonS3Client(region)
- : new AmazonS3Client(awsCredentials, region);
+ ? new AmazonS3Client(clientConfig)
+ : new AmazonS3Client(awsCredentials, clientConfig);
}
if (configuration.UseTemporaryCredentials)
{
- return new AmazonS3Client(await GetTemporaryCredentialsAsync(configuration), region);
+ return new AmazonS3Client(await GetTemporaryCredentialsAsync(configuration), clientConfig);
}
if (configuration.UseTemporaryFederatedCredentials)
{
return new AmazonS3Client(await GetTemporaryFederatedCredentialsAsync(configuration),
- region);
+ clientConfig);
}
Check.NotNullOrWhiteSpace(configuration.AccessKeyId, nameof(configuration.AccessKeyId));
Check.NotNullOrWhiteSpace(configuration.SecretAccessKey, nameof(configuration.SecretAccessKey));
- return new AmazonS3Client(configuration.AccessKeyId, configuration.SecretAccessKey, region);
+ return new AmazonS3Client(configuration.AccessKeyId, configuration.SecretAccessKey, clientConfig);
+ }
+
+ protected virtual AmazonS3Config CreateS3ClientConfig(AwsBlobProviderConfiguration configuration, RegionEndpoint region)
+ {
+ var clientConfig = new AmazonS3Config
+ {
+ RegionEndpoint = region
+ };
+
+ if (!configuration.ServiceURL.IsNullOrWhiteSpace())
+ {
+ clientConfig.ServiceURL = configuration.ServiceURL;
+ clientConfig.ForcePathStyle = true; // Required for most S3-compatible services
+ }
+
+ return clientConfig;
}
protected virtual AWSCredentials? GetAwsCredentials(