Amazon S3へデータの格納・取得を行う【AmazonS3Client】 C#編

2013.02.20

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

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にアクセスすることにします。一時証明書を用いる場合とそうでない場合の違いは後述します。プログラムの構成は下記のようになります。赤枠の部分を今回はご紹介します。

id_federation_csharp_04

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]