Amazon S3へデータの格納・取得を行う【AmazonS3Client】 C#編
C#でS3へファイルの格納・取得を行う
本記事ではC#でS3とやり取りを行うプログラムをご紹介します。プロジェクトでサンプルアプリケーションを作成していたのですが、意外と参考記事が少なかったので、ここにまとめておきます。参考記事は本記事最後に。
Java版のS3接続プログラムは弊社小室による下記が詳しいです:
・Amazon S3へデータの格納・取得を行う【AmazonS3Client】 Java編
https://dev.classmethod.jp/cloud/aws_s3_getobject_error/
Identity Federationとの統合
以前、AWS IAMのIdentity Federationを使うIdentity Broker(C#編)を書いたのですが、そこで紹介したプログラムを流用して、一時証明書を用いてS3にアクセスすることにします。一時証明書を用いる場合とそうでない場合の違いは後述します。プログラムの構成は下記のようになります。赤枠の部分を今回はご紹介します。
AmazonS3オブジェクトの取得
プログラム全体は記事の最後にご紹介するものとして、プログラムのポイントポイントを見ていきます。まずはS3にアクセスするためのクライアントであるAmazonS3を取得します。
var credentials = IdentityBroker.getToken("ユーザーID", "パスワード"); if (credentials == null) { sr.WriteLine("Authentication Failure."); return sb.ToString(); } var sessionAWSCredentials = new SessionAWSCredentials(credentials.AccessKeyId, credentials.SecretAccessKey, credentials.SessionToken); var s3 = AWSClientFactory.CreateAmazonS3Client(sessionAWSCredentials, RegionEndpoint.APNortheast1); //var s3 = AWSClientFactory.CreateAmazonS3Client(RegionEndpoint.APNortheast1); //一時証明書を用いない場合
ここでIdentityBrokerはC#でIdentity Brokerを作成する記事で作成したものです。ポイントは最後の3行になります。
- 一時証明書を用いる場合は明示的にSessionAWSCredentialsを作成し、それを引数にAWSClientFactory.CreateAmazonS3Client()を呼び出します。
- 通常の証明書の場合はAWSClientFactory.CreateAmazonS3Client()を引数なし、またはリージョン指定のみで呼び出します。
AWSClientFactory.CreateAmazonS3Client()は引数の指定方法が9通りあるので、ケースバイケースで利用することになりますが、大まかには上記の2パターンになるかと思います。
このS3アクセスクライアントを用いて以後の処理を行なっていきます。
※通常の証明書を利用した処理の場合、AWS SDK for .NETではApp.configに証明書を記入することになります。
バケット一覧の取得
次にS3へのPUT/GETの前に、バケット一覧を取得しておきたいと思います。
// List Objects var listObjectRequest = new ListObjectsRequest(); listObjectRequest.BucketName = bucketName; var response = s3.ListObjects(listObjectRequest); foreach (var item in response.S3Objects) { sr.WriteLine("Object Name: " + item.Key); }
上記では同期処理でバケット一覧を取得しています。WPFなどUIが関連するプログラムなどで処理を行う際は、上記のs3.ListObjectsの部分をs3.BeginListObjectsに変更し、コールバックメソッドを指定してS3にアクセスするようにすると良いでしょう。
オブジェクトの格納
次にS3へのオブジェクトの格納(PUT処理)を行います。
// Put Objects using (TransferUtility transferUtility = new TransferUtility(s3)) { TransferUtilityUploadRequest request = new TransferUtilityUploadRequest() .WithBucketName(bucketName) .WithKey(uploadObjectKey) .WithFilePath(targetLocalFolder + uploadObjectKey) .WithPartSize(partSize) .WithStorageClass(S3StorageClass.Standard) .WithTimeout(timeout) .WithSubscriber(UploadFileProgressCallback); transferUtility.Upload(request); sr.WriteLine("Upload Complete: " + uploadObjectKey); }
S3にPUT処理を行う際は、TransferUtilityを用います。TransferUtilityUploadRequestにバケット名、オブジェクトキー(ファイル名)、ローカルのファイルパス、分割アップロードサイズ(上記コードハイライト部分)等を指定しています。また、UploadFileProgressCallbackを指定することにより、非同期にファイルアップロード状況を取得することが可能です。
transferUtility.Upload()で同期的に処理を行なっていますが、ListBucketの場合同様、非同期で行いたい場合はtransferUtility.BeginUpload()メソッドを利用すると良いでしょう。
オブジェクトの取得
オブジェクトの取得(GET処理)もTransferUtilityを用いて行うことができます。
// Get Objects using (TransferUtility transferUtility = new TransferUtility(s3)) { TransferUtilityDownloadRequest downloadRequest = new TransferUtilityDownloadRequest() .WithBucketName(bucketName) .WithKey(downloadObjectKey) .WithFilePath(targetLocalFolder + downloadObjectKey) .WithTimeout(timeout) .WithSubscriber(DownloadFileProgressCallback); transferUtility.Download(downloadRequest); sr.WriteLine("Download Complete: " + downloadObjectKey); }
まとめ
今回はC#を用いてS3にファイルを格納・取得するプログラムを作成してみました。非常にスッキリとしたコードでS3にアクセスできたと思います。
参考:
・.NETからAWS S3のアップロード/ダウンロード - とむころりの開発日誌
http://tomcatch.blog38.fc2.com/blog-entry-9.html
Program.cs全コード
namespace IdentityBrokerSample { class Program { public static void Main(string[] args) { Console.Write(GetServiceOutput(args)); Console.Read(); }
public static string GetServiceOutput(string[] args) { StringBuilder sb = new StringBuilder(1024); using (StringWriter sr = new StringWriter(sb)) { if (args.Length < 2) { sr.WriteLine("Usage: IdentityBrokerSample name password"); return sb.ToString(); } var credentials = IdentityBroker.getToken(args[0], args[1]); if (credentials == null) { sr.WriteLine("Authentication Failure."); return sb.ToString(); } var sessionAWSCredentials = new SessionAWSCredentials(credentials.AccessKeyId, credentials.SecretAccessKey, credentials.SessionToken); var s3 = AWSClientFactory.CreateAmazonS3Client(sessionAWSCredentials, RegionEndpoint.APNortheast1); //var s3 = AWSClientFactory.CreateAmazonS3Client(RegionEndpoint.APNortheast1); //一時証明書を用いない場合 string bucketName = "mybucketname"; string targetLocalFolder = @"C:\Users\fukuda.tomonari\Desktop\"; string downloadObjectKey = @"sample.txt"; string uploadObjectKey = @"sample.txt"; long partSize = 1 * 1024 * 1024; // 1MB int timeout = 5 * 60 * 1000; // 5min try { // List Objects var listObjectRequest = new ListObjectsRequest(); listObjectRequest.BucketName = bucketName; var response = s3.ListObjects(listObjectRequest); foreach (var item in response.S3Objects) { sr.WriteLine("Object Name: " + item.Key); } // Put Objects using (TransferUtility transferUtility = new TransferUtility(s3)) { TransferUtilityUploadRequest request = new TransferUtilityUploadRequest() .WithBucketName(bucketName) .WithKey(uploadObjectKey) .WithFilePath(targetLocalFolder + uploadObjectKey) .WithPartSize(partSize) .WithStorageClass(S3StorageClass.Standard) .WithTimeout(timeout) .WithSubscriber(UploadFileProgressCallback); transferUtility.Upload(request); sr.WriteLine("Upload Complete: " + uploadObjectKey); } // Get Objects using (TransferUtility transferUtility = new TransferUtility(s3)) { TransferUtilityDownloadRequest downloadRequest = new TransferUtilityDownloadRequest() .WithBucketName(bucketName) .WithKey(downloadObjectKey) .WithFilePath(targetLocalFolder + downloadObjectKey) .WithTimeout(timeout) .WithSubscriber(DownloadFileProgressCallback); transferUtility.Download(downloadRequest); sr.WriteLine("Download Complete: " + downloadObjectKey); } } catch (AmazonS3Exception ex) { if (ex.ErrorCode != null && (ex.ErrorCode.Equals("InvalidAccessKeyId") || ex.ErrorCode.Equals("InvalidSecurity"))) { sr.WriteLine("Please check the provided AWS Credentials."); sr.WriteLine("If you haven't signed up for Amazon S3, please visit http://aws.amazon.com/s3"); } else { sr.WriteLine("Caught Exception: " + ex.Message); sr.WriteLine("Response Status Code: " + ex.StatusCode); sr.WriteLine("Error Code: " + ex.ErrorCode); sr.WriteLine("Request ID: " + ex.RequestId); sr.WriteLine("XML: " + ex.XML); } } sr.WriteLine("Press any key to continue..."); } return sb.ToString(); } static void DownloadFileProgressCallback(object sender, WriteObjectProgressArgs e) { } static void UploadFileProgressCallback(object sender, UploadProgressArgs e) { } } } [/csharp]