【Unity】AWS S3から色々な方法でデータを取得する

# はじめに
AWSのS3に格納したファイルの取得方法を色々試したのでメモを残します。

# 事前準備
1. S3バケットを作成し、取得したいファイルをアップロードしておく。
1. Unity側で使用するIAMユーザーを作成し、S3に対してRead可能なロールを割り当てておく。<br>
※シークレットキーは一度画面遷移すると確認できなくなるのでメモっておくこと。
1. [Nuget](https://www.nuget.org/)から次のdllのnupkgファイルを取得し、拡張子を".zip"に変更して展開する。
    * AWSSDK.Core.dll
    * AWSSDK.S3.dll
1. "Assets/pluginsディレクトリに格納する。（適当な場所でよいかも）
1. 上記dllが依存しているdllもNugetから取得し、同ディレクトリに格納する。
　　(NugetのDependenciesタブから.NETStandard2.0の依存dllを追跡する。)
　私が実施した際は次のdllが依存していました。
    * Microsoft.Bcl.AsyncInterfaces.dll
    * System.Runtime.CompilerServices.Unsafe.dll
    * System.Threading.Tasks.Extensions.dll

# ソースコード例
適当なゲームオブジェクトにアタッチし、Inspectorのフィールドを埋めると動作する。
* 以下のコードで、テキストの取得・Jsonの取得およびデシリアライズ・ファイルのダウンロードが可能です。
* そのままだと使いづらいので取得部分以外は改造した方が良いと思います。
* 非同期部分はUniTaskの導入を推奨します。 
* 取得失敗した場合のケースは考慮していません。

```cs:S3Connecter.cs
using UnityEngine;
using Amazon.S3;
using Amazon.S3.Model;
using System.IO;
using UnityEngine.UI;
using Amazon.S3.Transfer;
using Newtonsoft.Json;
using System.Threading.Tasks;

public class S3Connecter : MonoBehaviour
{
    enum RegionAPNorth
    {
        TOKYO, // 東京
        SEOUL, // ソウル
        OSAKA // 大阪
    }

    [SerializeField, Header("バケット名")]
    string _bucketName;

    [SerializeField, Header("アクセスキー")]
    string _accessKey;

    [SerializeField, Header("シークレットキー")]
    string _secretKey;

    [SerializeField, Header("リージョン")]
    RegionAPNorth _regionEndpoint;

    [SerializeField, Header("取得するファイル名")]
    string _downloadFileName;

    [SerializeField, Header("ダウンロードパス")]
    string _downloadPass = @"C:\temp\";

    [SerializeField, Header("ログを表示するテキスト")]
    Text _logtext;


    /// <summary>
    /// S3上のテキストを取得する。
    /// </summary>
    public async void DispTextFile()
    {
        AmazonS3Client s3Client = GetAmazonS3Client();
        GetObjectResponse getObjectResponse = await s3Client.GetObjectAsync(_bucketName, _downloadFileName);
        using (StreamReader reader = new StreamReader(getObjectResponse.ResponseStream))
        {
            _logtext.text = await reader.ReadToEndAsync();
        }
    }
    /// <summary>
    /// S3上のJsonファイルを取得し、デシリアライズする。
    /// </summary>
    public async Task<RequestType> JsonDeserialize<RequestType>()
    {
        AmazonS3Client s3Client = GetAmazonS3Client();
        GetObjectResponse getObjectResponse = await s3Client.GetObjectAsync(_bucketName, _downloadFileName);

        RequestType deserializedInstance;
        using (StreamReader reader = new StreamReader(getObjectResponse.ResponseStream))
        {
            // Jsonデシリアライズ
            JsonSerializer serializer = new JsonSerializer();
            deserializedInstance = (RequestType)serializer.Deserialize(reader, typeof(RequestType));
        }
        return deserializedInstance;
    }

    /// <summary>
    /// ファイルをダウンロードし、指定のディレクトリに格納する。
    /// </summary>
    public void DownloadFile()
    {
        AmazonS3Client s3Client = GetAmazonS3Client();
        using (TransferUtility fileTransferUtility = new TransferUtility(s3Client))
        {
            fileTransferUtility.Download(_downloadPass + _downloadFileName, _bucketName, _downloadFileName);
            _logtext.text = "ダウンロードに成功しました";
        }
    }

    /// <summary>
    /// S3クライアントの取得
    /// </summary>
    private AmazonS3Client GetAmazonS3Client()
    {
        return new AmazonS3Client(_accessKey, _secretKey, GetRegionInstance(_regionEndpoint));
    }

    /// <summary>
    /// リージョンインスタンス取得
    /// </summary>
    private Amazon.RegionEndpoint GetRegionInstance(RegionAPNorth region)
    {
        Amazon.RegionEndpoint retRegion = region switch
        {
            RegionAPNorth.TOKYO => Amazon.RegionEndpoint.APNortheast1,
            RegionAPNorth.SEOUL => Amazon.RegionEndpoint.APNortheast2,
            RegionAPNorth.OSAKA => Amazon.RegionEndpoint.APNortheast3,
            _ => null

        };
        return retRegion;
    }
}
```
# その他
S3の使用方法について調べているとAWSSDK for Unity なるものが存在していた様ですが、ここ最近のUnityバージョンには非対応らしいので注意が必要です。