Unity5.3からAWSのS3ストレージへファイルをアップロードするメモです。
キーポイント
- AWSが用意しているAWS Mobile SDK for Unityを利用する
- S3への認証はCognito Identityを用いる
参考リンク
手順
S3バケットの作成
任意の名前でS3バケットを生成しておきます。Regionはどこでも構いません。今回はTokyoリージョンにtest-bucket-unityとバケット名で作成しました。
以下のポリシーは、test-bucket-unity バケット内のすべてのファイルを表示できるアクセス許可をすべての閲覧者に付与します。このポリシーをコピーし、[Bucket Policy Editor] に貼り付けます。
{ "Version":"2012-10-17", "Statement": [{ "Sid": "Allow Public Access to All Objects", "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::test-bucket-unity/*" } ] }
Permissionの追加でAny Authenticated AWS UserにListとUpload/Delete権限を付与します。
Identify Pool Idの取得
AWSログイン後、Amazon Cognito管理ページに移動します。 Cogniteは2016年6月現在US-EASTリージョンでしか提供されていません。
Manage Federated Identitiesに進みます。
Identify pool nameを名づけて、Enable access to unauthenticated identitiesをチェックしてCreate PoolをクリックしてIdentify Poolを作成します。
アクセス権限設定のためのIAMロールを新規に作成します。特に規定の値から何も変更せずに「許可」をクリックします。
次に進むと、UnityからAWSへCognito Identify pool IDを用いたアクセスコードのサンプルが表示されます。
IAMロール変更(S3アクセス権限付与)
次に作成したIdentify poolでS3へアクセスできるようにしておきましょう。IAMコンソールに移動して、ロールを見ると先ほど生成したIAMロール(今回の場合Cognito_test_pool_nameAuth_Role)がありますので設定を変更します。
S3へのフルアクセスポリシーをアタッチします。
これで、S3へのアクセス権限は完了。
Unity上でAWS利用
What is the AWS Mobile SDK for Unity? ページからAWS Mobile SDK for Unityをダウンロードします。
解凍したフォルダから下記2つのパッケージをインポートします。
- AWSSDK.S3.3.1.7.2.unitypackage
- AWSSDK.IdentityManagement.3.1.4.3.unitypackage
S3ExampleデモシーンでS3にアクセスできることを確認しましょう。
S3にファイルをアップロードするクラスを作ったのでシェアしておきます。
using UnityEngine; using Amazon.S3; using Amazon.S3.Model; using System.IO; using Amazon.CognitoIdentity; using Amazon; public class s3upload { private CognitoAWSCredentials credentials; private string backetNameString; private RegionEndpoint regionVal; /// <summary> /// コンストラクタ /// </summary> /// <param name="IdentityPoolId">CognitoのIdentify Pool ID</param> /// <param name="backetName">バケット名</param> /// <param name="region">Region未指定の場合はUSEast1</param> public s3upload(string IdentityPoolId, string backetName, RegionEndpoint region=null) { if (region == null) { regionVal = RegionEndpoint.USEast1; } //Region未指定の場合はUSEast1を設定 credentials = new CognitoAWSCredentials(IdentityPoolId, regionVal); backetNameString = backetName; } /// <summary> /// 指定ファイルをS3バケットにアップロードします /// </summary> /// <param name="inputFileFullPath">アップロードするローカルファイルパス</param> /// <param name="uploadS3path">S3パス。fol/filenameと指定するとfolフォルダ以下にアップロードする</param> public void uploadFileToS3(string inputFileFullPath, string uploadS3path) { AmazonS3Client S3Client = new AmazonS3Client(credentials, regionVal); //ファイル読み込み var stream = new FileStream(inputFileFullPath, FileMode.Open, FileAccess.Read, FileShare.Read); //リクエスト作成 var request = new PostObjectRequest() { Bucket = backetNameString, Key = uploadS3path, InputStream = stream, CannedACL = S3CannedACL.Private }; //アップロード S3Client.PostObjectAsync(request, (responseObj) => { if (responseObj.Exception == null){ //Success Debug.Log(uploadS3path + " :Upload successed"); } else{Debug.LogError(string.Format("\n receieved error {0}", responseObj.Response.HttpStatusCode.ToString()));} }); } }
利用するには下記のようにする
using UnityEngine; using System.Collections; using Amazon; public class test : MonoBehaviour { // Use this for initialization void Start () { UnityInitializer.AttachToGameObject(this.gameObject); string IdentityPoolId = "us-east-1:6f62b9a3-8bbc-xxxx-xxxx-xxxxxxxxxx"; string backetName = "test-bucket-unity"; string inputFileFullPath = @"C:\temp\zipicon.png"; string uploadS3path = "fol1/zipicon.png"; s3upload s3 = new s3upload(IdentityPoolId, backetName); s3.uploadFileToS3(inputFileFullPath, uploadS3path); } // Update is called once per frame void Update () { } }
メモ
Exception: Main thread has not been set, is the AWSPrefab on the scene?エラーは
UnityInitializer.AttachToGameObject(this.gameObject);
で対処
Editorモードでは動かない?。。。。->動かないようです。。
追記(2016/09/04)
エディタモードでは上記方法でS3へのアップロードができないのでc#でコマンドライン上で動くコンソールアプリを開発しUnityから呼び出すことにした。コンソールアプリでは若干実装の方法が異なる
https://github.com/from2001/S3Uploader
1, Visual Studioでコンソールアプリケーションプロジェクトを作成
2,必要ライブラリをNugetでインストール
Install-Package AWSSDK.S3 Install-Package AWSSDK.CognitoIdentity
3,s3upload.cs(コンソールアプリ用)を作成
using System; using Amazon.S3; using Amazon.CognitoIdentity; using Amazon; using Amazon.S3.Transfer; public class s3upload { private CognitoAWSCredentials credentials; private string g_backetNameString; private string g_RegionSystemName_backet; /// <summary> /// コンストラクタ /// </summary> /// <param name="IdentityPoolId">CognitoのIdentify Pool ID</param> /// <param name="backetName">バケット名</param> /// <param name="RegionSystemName"> us-west-1, ap-northeast-1, ap-south-1 etc..</param> public s3upload(string IdentityPoolId, string RegionSystemName_backet, string backetName, string RegionSystemName_IdentityPoolId) { RegionEndpoint regionVal = RegionEndpoint.GetBySystemName(RegionSystemName_IdentityPoolId); credentials = new CognitoAWSCredentials(IdentityPoolId, regionVal); g_backetNameString = backetName; g_RegionSystemName_backet = RegionSystemName_backet; } /// <summary> /// 指定ファイルをS3バケットにアップロードします /// </summary> /// <param name="inputFileFullPath">アップロードするローカルファイルパス</param> /// <param name="uploadS3path">S3パス。fol/filenameと指定するとfolフォルダ以下にアップロードする</param> public void uploadFileToS3(string inputFileFullPath, string uploadS3path) { RegionEndpoint Region_backet = RegionEndpoint.GetBySystemName(g_RegionSystemName_backet); AmazonS3Client S3Client = new AmazonS3Client(credentials, Region_backet); TransferUtility fileTransferUtility = new TransferUtility(S3Client); //ファイル転送 fileTransferUtility.Upload(inputFileFullPath, g_backetNameString, uploadS3path); Console.WriteLine("Uploaded: " + uploadS3path); } /// <summary> /// 指定フォルダをS3バケットにアップロードします /// </summary> /// <param name="inputFileFullPath">アップロードするローカルフォルダパス</param> /// <param name="uploadS3dir">S3パス。fol/と指定するとfolフォルダ以下にアップロードする</param> public void uploadFolderToS3(string inputFolderFullPath, string uploadS3dir) { //uploadS3pathの末尾が/でない場合は/を付加 if (uploadS3dir.EndsWith("/")==false) { uploadS3dir = uploadS3dir + "/"; } //inputFolderFullPathの末尾が\でない場合は\を付加 if (inputFolderFullPath.EndsWith("\\") == false) { inputFolderFullPath = inputFolderFullPath + "\\"; } //ファイル一覧取得 System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(inputFolderFullPath); System.IO.FileInfo[] files = di.GetFiles("*", System.IO.SearchOption.AllDirectories); //1ファイルずつアップロード foreach (System.IO.FileInfo f in files) { string uploadS3path; uploadS3path = uploadS3dir + f.FullName.Replace(inputFolderFullPath, ""); uploadS3path = uploadS3path.Replace(@"\", "/"); uploadFileToS3(f.FullName, uploadS3path); } } }
4,呼び出し方は同じ
S3アップロード用のコマンドラインツールはこちらにアップしました。
S3Uploader