当前位置: 首页 > 工具软件 > S3Uploader > 使用案例 >

.Net Core 访问AWS S3

姬英耀
2023-12-01

.Net Core 访问AWS S3

最近工作中用到了AWS S3 存储文件,而且是.Net Core项目,第一次用.Net Core访问S3所以折腾一会。
publish到本地之后还是无法访问,只有在Debug是可行。后续解决之后再进行更新,如果有大神知道如何解救可以帮忙知道一下。
参考文档

NuGut包

访问S3 需要安装几个AWS的NuGet包。不要安装多余的.NET Framework AWS 的包,刚开始犯过这个愚蠢的错误,会有版本冲突。

  1. AWSSDK.S3。
  2. AWSSDK.Extensions.NETCore.Setup

配置appsettings.Development.json.

以下配置显示您可以添加到项目 appsettings.Development.json 文件中用于提供 AWS 设置的值的示例。
ProfilesLocation 可以不填会自动找到,填写后会读取指定路径下的credentials文件

  "AWS": {
    "Profile": "replatform-dev",
    "Region": "ap-southeast-2",
    "ProfilesLocation": "C:\\aws\\credentials"
  },

配置Startup.cs文件

读取appseting.json 的配置信息

public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
        .AddEnvironmentVariables();
    Configuration = builder.Build();
}

以下是对AWS实现注入,有关.Net Core 依赖注入的问题可以查询相关文档

        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
           	...
           	
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
            services.AddAWSService<IAmazonS3>();

            services.AddOptions();
            services.AddDefaultAWSOptions(Configuration.GetAWSOptions());
            
            ...
        }

功能实现

基础配置都已经完成,接下来就是写代码调用AWS S3读写文件,我进行了简单地封装,直接上代码。
为了精简篇幅我将一些多余的方法去除掉,只留下能实现获取S3Client的部分。

public class AwsStorageHelper
    {

        IAmazonS3 S3Client { get; set; }

        public static string BaseURL { get; set; }

        public AwsStorageHelper(IAmazonS3 s3Client)
        {
            S3Client = s3Client;
        }
		
        /// <summary>
        /// Get S3 Client for connecting to S3
        /// </summary>
        /// <returns>S3 Client</returns>
        public IAmazonS3 GetClient()
        {

            if (S3Client != null)
            {
                return S3Client;
            }
			//一下是老外同事加的代码,为了确保不出意外,我个人认为没必要,S3Client会通过注入的方式创建实例,不出意外应该不会为null
            var config = new AmazonS3Config { ServiceURL = BaseURL };

            return S3Client = new AmazonS3Client(config);
        }
    }

对BaseUrl的赋值是在Startup.cs中实现,同时赋值的还有Bucket。
Url和Bucket的信息都配置在appseting.json里。

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
	...
 	var builder = new ConfigurationBuilder()
               .SetBasePath(env.ContentRootPath)
               .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
               .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
               .AddEnvironmentVariables();

            IConfigurationRoot configuration = builder.Build();
            IConfigurationSection appConfigSection = configuration.GetSection("AppConfig");

     AwsStorageClient.BucketName = configuration.GetSection("AWSParameters")
                                                               .GetSection("Bucket").Value;
     AwsStorageHelper.BaseURL = configuration.GetSection("AWSParameters")
                                                               .GetSection("BaseURL").Value;
      ...
}

接下来就是一个实现读写S3的类,我是使用Stream读写文件,可以根据实际情况来实现方法


public class AwsStorageClient : IStorageClient
    {
        /// <summary>
        /// Storage Helper - this is injected by Windsor. Provides the S3 client.
        /// </summary>
        public AwsStorageHelper Storage { get; set; }

        /// <summary>
        /// Bucket Name - this must be set before use.
        /// </summary>
        public static string BucketName { get; set; }

        public bool Exists(string filePath)
        {
            EnsureBucketName();
            filePath = CleanFilePath(filePath);

            var client = Storage.GetClient();
            ListObjectsV2Request request = new ListObjectsV2Request
            {
                BucketName = BucketName,
            };

            //var s3DirectoryInfo = new S3DirectoryInfo(client, BucketName);

            ListObjectsV2Response response = client.ListObjectsV2Async(request).Result;

            return response.S3Objects.Exists(c => c.Key == filePath);
        }

        public void WriteFile(string filePath, Stream fileContent)
        {
            EnsureBucketName();
            filePath = CleanFilePath(filePath);

            var client = Storage.GetClient();
            using (var uploader = new TransferUtility(client))
            {
                uploader.Upload(fileContent, BucketName, filePath);
            }
        }


        public long FileSize(string filePath)
        {
            EnsureBucketName();
            filePath = CleanFilePath(filePath);

            var client = Storage.GetClient();
            using (var response = client.ListObjectsAsync(new ListObjectsRequest { BucketName = BucketName, Prefix = filePath }))
            {
                if (response.Result.S3Objects.Count > 0)
                {
                    return response.Result.S3Objects.First().Size;
                }

                return 0;
            }
        }

        public string FileType(string filePath)
        {
            return "application/octet-stream";
        }

        public Stream ReadFile(string filePath)
        {
            EnsureBucketName();
            filePath = CleanFilePath(filePath);

            var client = Storage.GetClient();
            var response = client.GetObjectAsync(BucketName, filePath);
            return response.Result.ResponseStream;

        }

        private void EnsureBucketName()
        {
            if (BucketName == string.Empty)
            {
                throw new InvalidBucketNameException("Bucket Name must be set before using the S3 storage client");
            }
        }

        private string CleanFilePath(string path)
        {
            // remove leading slashes
            if (path.Length > 0 && path.Substring(0, 1) == "/")
            {
                path = Regex.Replace(path, "^[/]+(.*)$", "$1");
            }

            return path;
        }


    }

 类似资料: