最近工作中用到了AWS S3 存储文件,而且是.Net Core项目,第一次用.Net Core访问S3所以折腾一会。
publish到本地之后还是无法访问,只有在Debug是可行。后续解决之后再进行更新,如果有大神知道如何解救可以帮忙知道一下。
参考文档
访问S3 需要安装几个AWS的NuGet包。不要安装多余的.NET Framework AWS 的包,刚开始犯过这个愚蠢的错误,会有版本冲突。
以下配置显示您可以添加到项目 appsettings.Development.json 文件中用于提供 AWS 设置的值的示例。
ProfilesLocation 可以不填会自动找到,填写后会读取指定路径下的credentials文件
"AWS": {
"Profile": "replatform-dev",
"Region": "ap-southeast-2",
"ProfilesLocation": "C:\\aws\\credentials"
},
读取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;
}
}