[Xamarin.Mac] AWS SDKでS3 Bucket内のオブジェクトを一覧してみました
1 はじめに
CX事業本部の平内(SIN)です。
Xamarin.Macを使用すると、C#でネイティブなMacのアプリが作成可能です。 ここでは、私自身がXamarin.Macに入門して学習した事項を覚書として書かせて頂いています。
今回は、特定のS3バケットのオブジェクトを一覧してみました。
2 NuGetパッケージ
Visual Studioでは、パッケージの管理は、NuGetで行うことができます。
検索で、「awssdk」と入れてみると、作成者が、Amazon Web Servicesとなった公式のSDK(パッケージ)が検索できます。
今回追加したのは、S3とCognitoIdentityの2つですが、依存関係で必要なパッケージも一緒にダウンロードされます。
3 Cognito
プログラムからS3にアクセスするために、CognitoでプールIDを作成しています。
ロールに付与したパーミッションは、特定のバケットのオブジェクト一覧と、取得のみになっています。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:ListBucket" ], "Resource": "arn:aws:s3:::xamarin-s3-sample" }, { "Effect": "Allow", "Action": [ "s3:getObject" ], "Resource": "arn:aws:s3:::xamarin-s3-sample/*" } ] }
4 S3アクセス
Cognitoの認証でS3バケットにアクセスするために作成したクラスは、以下のとおりです。
コンストラクタで、Cognito認証によるS3クライアントを生成し、2つのメソッド(一覧取得とオブジェクト取得)が利用可能になっています。
public class S3Client { // Cognito Pool ID private string poolId = "ap-northeast-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; // アクセス先のバケット private string bucketName = "xamarin-s3-sample"; private AmazonS3Client client; public S3Client() { // クレデンシャル取得 var cognitoCredentials = new CognitoAWSCredentials(poolId, RegionEndpoint.APNortheast1); // S3クライアントの生成 client = new AmazonS3Client(cognitoCredentials); } // バケット内のオブジェクト一覧取得 public async System.Threading.Tasks.Task<List<string>> getObjectsAsync() { var result = await client.ListObjectsAsync(bucketName); return result.S3Objects.Select(o => o.Key).ToList(); } // 指定したオブジェクトの取得 public async System.Threading.Tasks.Task<string> getObjectAsync(string key) { var request = new GetObjectRequest { BucketName = bucketName, Key = key }; var response = await client.GetObjectAsync(request); var reader = new StreamReader(response.ResponseStream); return reader.ReadToEnd(); } }
5 画面構成
メインとなるウインドウは、NSSplitViewで3分割され、下のウインドウの左側にNSCollectionView、右側にNSTextViewを配置しています。 それぞれ、CollectionViewとTextViewという名前でOutletが作成されています。
コレクションビューのアイテム用ビューは、Labelが、ファイル名表示用にバインディングされています。
6 DataSource/Delegate
コレクションビューのデータソースは、バケット内のオブジェクト一覧を保持するリストFilesで動作しています。
public class CollectionViewDataSource: NSCollectionViewDataSource { public List<string> Files = new List<string>(); public CollectionViewDataSource() { } public override NSCollectionViewItem GetItem(NSCollectionView collectionView, NSIndexPath indexPath) { var item = collectionView.MakeItem("cell", indexPath) as ItemViewController; item.FileName = Files[(int)indexPath.Item]; return item; } public override nint GetNumberofItems(NSCollectionView collectionView, nint section) { return Files.Count; } }
デリゲートでは、コンストラクタでViewControllerをコピーしておいて、選択が変化したタイミングで、ItemSelectedAsync()を呼び出しています。
public class CollectionViewDelegate: NSCollectionViewDelegateFlowLayout { ViewController ViewController; public CollectionViewDelegate(ViewController ViewController) { this.ViewController = ViewController; } public override void ItemsSelected(NSCollectionView collectionView, NSSet indexPaths) { var paths = indexPaths.ToArray<NSIndexPath>(); _ = ViewController.ItemSelectedAsync((int)paths[0].Item); } }
7 ViewController
メインとなるViewControllerです。
S3を操作するクラスをコンストラクタで生成しています。
起動時、若しくはReloadボタンが押されたタイミングで、バケットの一覧を取得して、左側のコレクションビューを初期化します。また、コレクションビューの選択が変化したタイミングで、右側のテキストビューを更新しています。
public partial class ViewController : NSViewController { S3Client s3client; public ViewController(IntPtr handle) : base(handle) { s3client = new S3Client(); } public override void ViewDidLoad() { base.ViewDidLoad(); // PictureViewControllerの登録 CollectionView.RegisterClassForItem(typeof(ItemViewController), "cell"); // DataSource CollectionView.DataSource = new CollectionViewDataSource(); // Flow layout var flowLayout = new NSCollectionViewFlowLayout() { ItemSize = new CGSize(100, 100), SectionInset = new NSEdgeInsets(10, 10, 10, 20), MinimumInteritemSpacing = 10, MinimumLineSpacing = 10 }; CollectionView.WantsLayer = true; CollectionView.CollectionViewLayout = flowLayout; // Delegate CollectionView.Delegate = new CollectionViewDelegate(this); //Reloadボタン ReloadButton.Activated += ReloadButton_Activated; //Reload _ = ReloadObjectsAsync(); } // Reloarボタンのアクション private void ReloadButton_Activated(object sender, EventArgs e) { _ = ReloadObjectsAsync(); } // リロード(一覧の再取得) async Task ReloadObjectsAsync() { ((CollectionViewDataSource)CollectionView.DataSource).Files = await s3client.getObjectsAsync(); CollectionView.ReloadData(); } // 選択が変化した際に呼び出せれる public async Task ItemSelectedAsync(int index) { var key = ((CollectionViewDataSource)CollectionView.DataSource).Files[index]; Console.WriteLine(key); var text = await s3client.getObjectAsync(key); Console.WriteLine(text); TextView.Value = text; } // ・・・略・・・
8 最後に
AWS SDKは、DotNet対応版が揃っており、Visual Studioでは、これをNuGetで簡単に導入できます。
おかげで、Xamarin.Macからでも、AWSのリソースの利用は、非常に簡単だと思います。