The process of connecting Unity to AWS S3, AWS SDK for Unity pitfall records

AWS S3, Amazon's resource server service, has been studying this content recently. Record the content of the pitfalls.

After studying the two parts of AWS SDK for unity and AWS SDK for .net
, it is difficult to connect to unity. The main reason is that there is no official API, and the unity version is used based on the use of the .net version.


The API naming of AWS SDK is similar regardless of the platform, and is mainly divided into 3 series

  1. List query
  2. Get Get, download
  3. Put upload

Main interfaces:

initialization

AmazonS3Client

m_AWSClient = new AmazonS3Client(strAccessKey, strSecretKey, regionEndpoint)

AccessKey, SecretKey, EndPoint need to be passed in during construction

Object operations

GetObject
PutObject

There was a problem under Unity.
GetObject could not obtain the download progress, so this API was abandoned and UnityWebRequest was used for downloading. Then a bunch of exceptions occurred. Here are two key points:

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;

After setting it up, it will be normal.

PutObject, upload a file. Normally, we would do this upload operation in a non-Runtime mode under the Editor, but a very strange thing happened in AWS. The main object AmazonS3Client reported an error, saying that it was not initialized. AmazonS3Client needs to be called before new

UnityInitializer.AttachToGameObject(this.gameObject);

I was instantly shocked. This is a Runtime API, which means uploading needs to be done while Unity is running. After testing, I found that it is indeed possible.

Permission operation

GetACL
PutACL
Get has no problem. I tried Put under unity and reported a WebRequestHeader error. emm...according to experience, the request lacks header information, so just complete the header information. However, AWS SDK The dll is packaged. This is embarrassing. It is not necessary to intercept the packet and then send it out.
So I tried the .net version again, and it was no problem at all and could be used normally. This is amazing. But it works.

Get list

ListObjects
encountered a problem when obtaining the list. AWS SDK requested content under a certain path and returned up to 1,000 file information. Any more would be gone. Debugging found that there is a field NextMarker in the returned structure ListObjectsResponse .
There is also a field Marker in ListObjectsRequest. I tried passing the mark returned for the first time to the next request, and it was successful. Therefore, AWS returns the list information according to paging logic, with an upper limit of 1,000. It makes sense if you think about it carefully. For the sake of performance and transmission bandwidth, in order to avoid the file size being too large, paging is adopted.

		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;
				}
			}
		}

I encountered a problem when downloading a text from AWS S3.
I downloaded the text and obtained the text information through UnityWebRequest, and found that the string content was different from the uploaded content.

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

After the download is completed, task.downloadHandler.text is obtained;
debug and see the content, which is the same as the text content I used when uploading. But the subsequent logic failed to parse the text content.
After debugging, the content of the string was the same, so I used string.toChatArray() to check the difference between each character. I found that the strings looked the same, but the first character was an empty char. String.trim was invalid for this empty char because of this The empty char and the second char form the first string word.

byte[] bytes = task.downloadHandler.data;

It is also wrong to get bytes, there is an empty content at the beginning.

Baidu got an explanation for this problem: https://blog.csdn.net/shersfy/article/details/54614720
It’s reasonable...add the code.

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

Then there is the issue of using .net production tools.

The description of .net in the official documentation is that the extension in visual studio can be searched for AWS and the plug-in can be found.
I pretended and found that it was of no use, I looked confused and didn’t explain it at all.

So I manually downloaded the .net dll.
It is valid as of September 3, 2021. https://sdk-for-net.amazonwebservices.com/latest/v3/aws-sdk-net45.zip.
If it is invalid, then go to the official website. I searched for sdk for .net in the search box of the website, but it was really troublesome to find it.
After decompressing the dll inside, add a reference, and use a tool under Windows to get it out.

Because generally, contracts are issued on dual platforms, ios and android. Android can be distributed on Windows. iOS packaging must be on a mac machine.
So I tried it and ran .net on mac.
The most straightforward method is a virtual machine.

My model is an M1 chip , oh my god. As of September 1, 2021, only parallels desktop can support windows virtual machines on the M1 chip. After installing the system, install .net. Run... fine no response

So the solution was replaced, because .net can be run directly under mac, and this can be done by Baidu.
donet can directly launch the .net core web console application.
I tried hello world and it ran normally without any problems.

Continue to try the relevant interfaces of AWS SDK for .net, but it fails. The error message is that AWSConfig is performing a local file operation and cannot find the path.
Over, too lazy to do it, declared failure .

Therefore, we still use SVN to synchronize the content that needs to be uploaded on the intranet, and operate it on a Windows machine.


Then there is the packaging. There is no problem in packaging the APK, but when running
, you will find that AmazonS3Client will throw an exception MissingMethodException when it is new.
AWS SDK for Unity contains many dlls after importing, and the so file has nothing to do with the log information.
So the problem comes from the dll. If you check the dll, you will find that
Insert image description here
the final Targets .net 3.5
is .net2.0 by default in unity2019. Then change it and increase the .net version of Unity.
Then I found that the error MissingMethodException still occurs.
Think about it, when running, the code cannot be found, but it is fine on the PC, then it may be cut by the code, then add link.(link.xml unity code Related to cutting, you can go to 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>

Continue, the error still occurs, appearing in

AWSConfigs.HttpClient = AWSConfigs.HttpClientOption.UnityWebRequest;

This line of code appears, and it is still a problem of reduction.

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

After a try

<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>

Woohoo, got through.

Then during the process of running the logic, I discovered a problem
related to List in the API of AWS SDK, such as ListBucketsAsync. When running under Android, there will be no CallBack, no timeout, and no inheritance. I am very confused. Because there is no API in the AWS SDK to prove the connection is successful, the idea of ​​using the bucket information to try whether the connection can be successful failed.

I complained again.
There is really no explanation in the official API of AWS. There is no official documentation of unity. I can only find it in the forum, but this kind of error is difficult to search for.

So let’s use Unity’s API. UnityWebRequest.

Security:

AWSProxy.Instance.GenerateDynamicURL

This API attempt is usable and returns the URL correctly.
It mainly produces a string of URLs with encrypted information.
If the account during initialization has permissions, the download can be successful, otherwise an HTTP error will be returned.


Programming is endless.
Everyone is welcome to communicate. If there is anything unclear or wrong, you can also chat with me privately.
My QQ 334524067 God-like Didi

Guess you like

Origin blog.csdn.net/qq_37776196/article/details/120034272