Unity を AWS S3 に接続するプロセス、AWS SDK for Unity の落とし穴記録

Amazon のリソース サーバー サービスである AWS S3 は、最近この内容を研究しています。落とし穴の内容を記録します。

AWS SDK for Unity と AWS SDK for .net の 2 つの部分を学習した後
、Unity に接続することが困難になりました。主な理由は、公式 API がなく、Unity バージョンが .net の使用に基づいて使用されていることです。バージョン。


AWS SDKのAPI命名はプラットフォームを問わず類似しており、主に3つのシリーズに分かれています

  1. リストクエリ
  2. 入手 入手、ダウンロード
  3. アップロードを入れる

主なインターフェース:

初期化

AmazonS3クライアント

m_AWSClient = new AmazonS3Client(strAccessKey, strSecretKey, regionEndpoint)

AccessKey、SecretKey、EndPoint は構築中に渡す必要があります

オブジェクトの操作

GetObject
PutObject

Unity で問題が発生しました。GetObject
がダウンロードの進行状況を取得できなかったため、この API は放棄され、UnityWebRequest がダウンロードに使用されました。その後、大量の例外が発生しました。重要な点は次の 2 つです:

AWSConfigs.HttpClient = AWSConfigs.HttpClientOption.UnityWebRequest;
public CertificateHandlerPublicKey Certificate { get; private set; } = new CertificateHandlerPublicKey();

public class CertificateHandlerPublicKey : CertificateHandler
{
    protected override bool ValidateCertificate(byte[] certificateData)
    {
        return true;
    }
}

uwq = UnityWebRequest.Get(strURL);
uwq.certificateHandler = AWSProxy.Instance.Certificate;

設定後は正常になります。

PutObject、ファイルをアップロードします。通常、このアップロード操作はエディターの下で非ランタイム モードで実行されますが、AWS で非常に奇妙なことが起こり、メイン オブジェクト AmazonS3Client が初期化されていないというエラーを報告しました。AmazonS3Client は新規作成の前に呼び出す必要があります

UnityInitializer.AttachToGameObject(this.gameObject);

これはランタイム API であるため、Unity の実行中にアップロードを行う必要があります。テストした結果、それが実際に可能であることがわかりました。

許可操作

GetACL
PutACL
Get は問題ありません Unity で Put してみたら WebRequestHeader エラーが出ました えっと…経験上、リクエストにヘッダー情報が欠けているのでヘッダー情報を入力するだけですが、AWS SDK には DLL がパッケージ化されています。これは恥ずかしいです。パケットをインターセプトしてから送信する必要はありません。
そこで、改めて.net版を試してみましたが、全く問題なく普通に使えました。これは素晴らしいです。しかし、それはうまくいきます。

リストの取得

ListObjects は
リストの取得時に問題が発生しました。AWS SDK は特定のパスの下のコンテンツをリクエストし、最大 1,000 個のファイル情報を返しました。それ以上は失われます。デバッグにより、返された構造体 ListObjectsResponse にNextMarkerフィールドがあることがわかりました。
ListObjectsRequest には Marker フィールドもあります。初めて返されたマークを次のリクエストに渡してみたところ、成功しました。したがって、AWS はページング ロジックに従って、上限 1,000 のリスト情報を返します。よく考えてみれば当然のことですが、パフォーマンスや伝送帯域の都合上、ファイルサイズが大きくなりすぎないようにページングが採用されています。

		public void GetList(string strUrlPre, out bool isSuc, out Dictionary<string, long> result)
		{
			isSuc = true;
			result = new Dictionary<string, long>();

			Debug.Log("AWSApi Connect,Start GetList");

			string strMark = null;
			while (true)
			{
				ListObjectsRequest request = new ListObjectsRequest();
				request.BucketName = m_strBucket;
				request.Prefix = strUrlPre;
				request.Marker = strMark;
				try
				{
					ListObjectsResponse response = m_AWSClient.ListObjects(request);
					var listServer = response.S3Objects;
					for (int i = 0; i < listServer.Count; i++)
					{
						result.Add(listServer[i].Key, listServer[i].Size);
					}
					strMark = response.NextMarker;
					if (string.IsNullOrEmpty(strMark))
					{
						break;
					}
				}
				catch (System.Exception e)
				{
					isSuc = false;
					Debug.LogError("AWSApi Connect, Error : " + e.Message);
					break;
				}
			}
		}

AWS S3 からテキストをダウンロードする際に問題が発生し、
テキストをダウンロードして UnityWebRequest でテキスト情報を取得したところ、文字列の内容がアップロードした内容と異なることがわかりました。

var task = UnityWebRequest.Get(strNetPath);
string strResult = task.downloadHandler.text;

ダウンロードが完了すると、task.downloadHandler.text が取得されるので、
デバッグして内容を確認します。これは、アップロード時に使用したテキスト コンテンツと同じです。しかし、後続のロジックはテキスト コンテンツを解析できませんでした。
デバッグ後、文字列の内容は同じだったので、string.toChatArray() を使用して各文字の違いを確認したところ、文字列は同じに見えましたが、最初の文字は空の文字でした。この空の文字は次の理由で無効です。 空の文字と 2 番目の文字は最初の文字列ワードを形成します。

byte[] bytes = task.downloadHandler.data;

バイトを取得するのも間違っており、最初に空のコンテンツがあります。

Baidu はこの問題について次の説明を入手しました: https://blog.csdn.net/shersfy/article/details/54614720
それは合理的です...コードを追加してください。

string strResult = task.downloadHandler.text;
if (strResult[0] == 65279)
{
    strResult = strResult.Substring(1);
}
callBack?.Invoke(true, strResult);

次に、.net 制作ツールの使用の問題があります。

公式ドキュメントの.netの記述は、visual Studioの拡張子をAWSで検索するとプラグインが見つかるとあります。
私はふりをしましたが、それが役に立たなかったことがわかり、混乱したように見え、まったく説明しませんでした。

そこで、.net dll を手動でダウンロードしました。2021
年 9 月 3 日の時点で有効です。https://sdk-for-net.amazonwebservices.com/latest/v3/aws-sdk-net45.zip。
無効な場合は、公式サイトにアクセスし、サイトの検索ボックスで.netのsdkを検索したのですが、見つけるのが非常に面倒でした。
内部の DLL を解凍した後、参照を追加し、Windows 上のツールを使用してそれを取り出します。

一般に、契約は ios と android のデュアル プラットフォームで発行されるためです。Android は Windows 上で配布できます。iOS パッケージは Mac マシン上に存在する必要があります。
そこで、Mac 上で .net を実行してみました。
最も簡単な方法は仮想マシンです。

私のモデルはM1 チップです、なんと、2021 年 9 月 1 日以降、M1 チップで Windows 仮想マシンをサポートできるのは、Parallels Desktop だけです。システムをインストールした後、.net をインストールします。実行してください...大丈夫、応答なし

.net は Mac 上で直接実行でき、Baidu によって実行できるため、ソリューションは置き換えられました。
donet は、.net core Web コンソール アプリケーションを直接起動できます。
hello worldを試してみたところ、問題なく正常に動作しました。

AWS SDK for .net の関連インターフェイスを引き続き試行しますが、失敗します。エラー メッセージは、AWSConfig がローカル ファイル操作を実行しているため、パスが見つからないというものです。
あまりにも怠惰なので、失敗を宣言しました

そのため、イントラネット上にアップロードする必要があるコンテンツの同期には今でも SVN を使用し、Windows マシン上で運用しています。


APK のパッケージ化には問題ありませんが、実行時に
AmazonS3Client が新しい場合に MissingMethodException 例外をスローすることがわかります。
AWS SDK for Unity にはインポート後の DLL が多数含まれており、so ファイルはログ情報とは関係ありません。
この問題は DLL に起因しています。DLL を確認すると、 unity2019 では
ここに画像の説明を挿入します
最終的な Targets .net 3.5 が
デフォルトで .net2.0 であることがわかります。その後、これを変更して Unity の .net バージョンを上げます。
その後、依然として MissingMethodException エラーが発生することがわかりました。
実行するとコードが見つかりませんが、PC 上では問題ないので、コードによってカットされる可能性があることを考えて、リンクを追加してください。(link.xml Unity コード)切断に関連する場合は、Baidu にアクセスできます)

<?xml version="1.0" encoding="utf-8"?>
<linker>
  <assembly fullname="AWSSDK.CognitoIdentity" preserve="all" />
  <assembly fullname="AWSSDK.Core" preserve="all" />
  <assembly fullname="AWSSDK.S3" preserve="all" />
  <assembly fullname="AWSSDK.SecurityToken" preserve="all" />
</linker>

続行してもエラーが発生し、次のように表示されます。

AWSConfigs.HttpClient = AWSConfigs.HttpClientOption.UnityWebRequest;

このコード行が表示されますが、これは依然として削減の問題です。

NullReferenceException: Object reference not set to an instance of an object.
      at Amazon.Runtime.Internal.UnityWebRequestWrapper..cctor () [0x00000] in <00000000000000000000000000000000>:0 
      at Amazon.AWSConfigs.set_HttpClient (Amazon.AWSConfigs+HttpClientOption value) 

AWS的内部异常是:
TypeInitializationException

試してみた後

<linker>
  <assembly fullname="UnityEngine">
    <type fullname="UnityEngine.Networking.UnityWebRequest" preserve="all" />
    <type fullname="UnityEngine.Networking.UploadHandlerRaw" preserve="all" />
    <type fullname="UnityEngine.Networking.UploadHandler" preserve="all" />
    <type fullname="UnityEngine.Networking.DownloadHandler" preserve="all" />
    <type fullname="UnityEngine.Networking.DownloadHandlerBuffer" preserve="all" />
  </assembly>
	<assembly fullname="AWSSDK.CognitoIdentity" preserve="all"/>
	<assembly fullname="AWSSDK.Core" />
	<assembly fullname="AWSSDK.S3" />
	<assembly fullname="AWSSDK.SecurityToken" />
</linker>

うおおお、通じた。

その後、ロジックを実行する過程で、
AWS SDK の API にある ListBucketsAsync などの List に関連する問題を発見しました。Android で実行すると、CallBack が発生せず、タイムアウトも発生せず、継承も発生しません。非常に混乱しています。AWS SDK には接続が成功したことを証明する API がないため、バケット情報を使用して接続が成功するかどうかを試すという考えは失敗しました。

またまた文句を言いましたが、
AWSの公式APIには本当に説明がありません、Unityの公式ドキュメントもありません、フォーラムでしか見つかりませんが、この手のエラーは探すのが大変です。

それではUnityのAPIを使ってみましょう。UnityWebRequest。

安全:

AWSProxy.Instance.GenerateDynamicURL

この API 試行は使用可能であり、URL を正しく返します。
主に、暗号化された情報を含む URL 文字列を生成します。
初期化中のアカウントに権限がある場合、ダウンロードは成功しますが、そうでない場合は HTTP エラーが返されます。


プログラミングには終わりがありません。
誰でも気軽にコミュニケーションできます。不明な点や間違いがある場合は、個人的にチャットすることもできます。My
QQ 334524067 God-like Didi

おすすめ

転載: blog.csdn.net/qq_37776196/article/details/120034272