鸟语天空
UnityWebRequest
post by:追风剑情 2019-12-12 16:43

示例一:上传视频


/// <summary>
/// 上传视频
/// </summary>
/// <param name="url">上传视频地址</param>
/// <param name="bytes">视频文件内容</param>
/// <returns></returns>
IEnumerator UpLoadVideo(string url, byte[] bytes)
{
	yield return null;
	WWWForm form = new WWWForm();
	form.AddField("id", 123);
	form.AddBinaryData("file", bytes, "my_video.mp4", "video/mp4");

	//byte[] bodyRaw = Encoding.UTF8.GetBytes(postDataString);//发送原始数据(即,数据不组织成表单)
        //UnityWebRequest request = new UnityWebRequest(url, "POST");
	UnityWebRequest request = UnityWebRequest.Post(url, form);
        request.timeout = 5;
        //https://docs.unity3d.com/ScriptReference/Networking.UnityWebRequest-useHttpContinue.html
        //true:  包含Expect: 100-Continue请求头, http会提前返回,这会导至后面的isNetworkError=true, responseCode=100
        //false: 确保http请求完毕后再返回
        request.useHttpContinue = false;
        request.chunkedTransfer = false; //false:不希望服务器分块返回数据
        request.SetRequestHeader("Content-Type", "application/json;charset=utf-8");
        //如果不指定post表单,需要这样上传原始数据
        //request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw);
        //request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
	//加上yield return 直到请求完成程序才会继续往下执行
	//yield return request.SendWebRequest();

	//调用后会立即返回,程序继续往下执行
	request.SendWebRequest();

	while (!request.isDone)
	{
		Debug.Log("上传进度: " + request.uploadProgress);
		yield return new WaitForSeconds(0.1f);
	}

	if (request.isHttpError || request.isNetworkError || request.responseCode != 200)
	{
		Debug.LogErrorFormat("上传视频出错\n{0}", request.error);
		yield break; //跳出协程
	}

	Debug.Log("上传视频成功!");
}

    // Post原始数据(即,非表单)
    public IEnumerator PostRaw(string url, string data, Action completedCallback = null, Action errorCallback = null)
    {
        yield return null;
        byte[] postBytes = Encoding.UTF8.GetBytes(data);
        DownloadHandler downloadHandler = new DownloadHandlerBuffer();
        UploadHandler uploadHandler = new UploadHandlerRaw(postBytes);
        UnityWebRequest request = new UnityWebRequest(url, UnityWebRequest.kHttpVerbPOST);
        request.SetRequestHeader("Content-Type", "application/json;charset=utf-8");
        request.SetRequestHeader("Accept", "application/json");
        //设置Accept-Charset会报InvalidOperationException异常
        //InvalidOperationException: Cannot override system-specified headers
        //request.SetRequestHeader("Accept-Charset", "utf-8");
        //request.SetRequestHeader("Content-Length", postBytes.Length.ToString());
        request.timeout = 30; //单位:秒
        request.useHttpContinue = false;//false:直接上传post数据,不需要发送前征询服务器情况
        request.chunkedTransfer = false;//false:不希望服务器分块返回数据
        request.downloadHandler = downloadHandler;
        //如果不指定post表单,需要这样上传原始数据
        request.uploadHandler = uploadHandler;
        //yield return request.SendWebRequest(); //同步请求(请求完成后才会继续往下执行)
        request.SendWebRequest(); //异步请求

        while (!request.isDone)
            yield return new WaitForSeconds(0.1f);
        if (request.isHttpError || request.isNetworkError || request.responseCode != 200)
        {
            Debug.LogErrorFormat("Post Error\n{0}", request.error);
            if (errorCallback != null)
                errorCallback();
            yield break;//跳出协程
        }
        Debug.Log("Post完成!");
        Debug.LogFormat("result={0}", request.downloadHandler.text);
        string json = request.downloadHandler.text;
        if (completedCallback != null)
            completedCallback(json);
    }

示例二:上传器


using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net.Mime;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
/// <summary>
/// 资源上传器 (multipart/form-data)
/// </summary>
public class AssetUpLoader : MonoBehaviour
{
	public static AssetUpLoader Instance { get; private set; }
	public bool dontDestroyOnLoad = true;
	public bool isSingleInstance = true;
	//上传队列
	private Queue<AssetObject> m_UploadQueue = new Queue<AssetObject>();
	private bool m_UpLoading = false;

	private void Awake()
	{
		if (dontDestroyOnLoad)
			DontDestroyOnLoad(gameObject);

		if (isSingleInstance)
			Instance = this;
	}

	private void Update()
	{
		if (m_UpLoading || m_UploadQueue.Count <= 0)
			return;

		AssetObject asset = m_UploadQueue.Dequeue();
		StartCoroutine(CoroutineUpLoad(asset));
	}

	public void UpLoad(AssetObject asset)
	{
		if (asset == null || string.IsNullOrEmpty(asset.url))
			return;
		m_UploadQueue.Enqueue(asset);
	}

	// 上传本地资源
	public void UpLoadLocal(AssetObject asset)
        {
		StartCoroutine(UpLoadLocalCoroutine(asset));
        }

	private IEnumerator UpLoadLocalCoroutine(AssetObject asset)
        {
		yield return null;
		Texture2D texture = null;
		using (WWW www = new WWW(asset.localPath))
                {
			while (!www.isDone)
				yield return null;

			if (!string.IsNullOrEmpty(www.error)) {
				Debug.LogErrorFormat("load local asset error: {0}\n{1}", www.error, www.url);
				yield break;
                        }
			texture = www.texture;
                }
		if (texture != null)
                {
			asset.bytes = texture.EncodeToJPG();
			m_UploadQueue.Enqueue(asset);
		}
	}

	/// <summary>
	/// 上传资源
	/// </summary>
	/// <param name="url">上传地址</param>
	/// <param name="bytes">资源内容</param>
	/// <returns></returns>
	IEnumerator CoroutineUpLoad(AssetObject assetObject)
	{
		Debug.LogFormat("begin upload: {0}", assetObject.fileName);
		m_UpLoading = true;
		yield return null;
		DownloadHandler downloadHandler = new DownloadHandlerBuffer();
		UnityWebRequest request = assetObject.unityWebRequest;
		request.downloadHandler = downloadHandler;
		request.SendWebRequest();

		while (!request.isDone)
		{
			Debug.Log("上传进度: " + request.uploadProgress);
			assetObject.uploadProgress = request.uploadProgress;
			if (assetObject.OnProgressCallback != null)
				assetObject.OnProgressCallback(assetObject);
			yield return new WaitForSeconds(0.1f);
		}

		if (request.isHttpError || request.isNetworkError || request.responseCode != 200)
		{
			Debug.LogErrorFormat("上传资源出错\n{0}\n{1}", request.error, assetObject.url);
			if (assetObject.OnErrorCallback != null)
				assetObject.OnErrorCallback(assetObject);
			assetObject.Dispose();
			m_UpLoading = false;
			yield break;
		}

		Debug.Log("上传资源完成!");
		Debug.LogFormat("{0}", request.downloadHandler.text);
		assetObject.result = request.downloadHandler.text;
		if (assetObject.OnCompletedCallback != null)
			assetObject.OnCompletedCallback(assetObject);
		assetObject.Dispose();
		m_UpLoading = false;
	}

	/// <summary>
	/// 表单编码方式
	/// Multipart格式文档
	//	https://www.cnblogs.com/greenerycn/archive/2010/05/15/csharp_http_post.html
	//	https://www.w3.org/TR/html401/interact/forms.html#h-17.13.4
	/// </summary>
	public class FormEnctype
	{
		//对于发送大量二进制数据或包含非ASCII字符的文本效率不高
		public const string APPLICATION_X_WWW_FORM_URLENCODED = "application/x-www-form-urlencoded";
		//提交包含文件,非ASCII数据和二进制数据的表单
		public const string MULTIPART_FORM_DATA = "multipart/form-data";
	}

	/// <summary>
	/// 资源对象
	/// </summary>
	public class AssetObject
	{
		public string headerContentType = FormEnctype.APPLICATION_X_WWW_FORM_URLENCODED;
		public string id = string.Empty; //用户ID
		public string url = string.Empty;
		public string localPath = string.Empty; //本地资源路径
		public byte[] bytes = null;
		//.jpg "image/jpeg"
		//.mp4 "video/mp4"
		public string mimeType = string.Empty;
		public string fileName = string.Empty;
		public float uploadProgress = 0.0f;
		public string result = string.Empty; //服务器返回数据

		public Action<AssetObject> OnCompletedCallback;
		public Action<AssetObject> OnProgressCallback;
		public Action<AssetObject> OnErrorCallback;

		public string MimeType
        {
			get
            {
				if (string.IsNullOrWhiteSpace(mimeType) && !string.IsNullOrWhiteSpace(fileName))
				{
					if (fileName.EndsWith(".jpg"))
						mimeType = "image/jpeg";
					else if (fileName.EndsWith(".png"))
						mimeType = "image/png";
					else if (fileName.EndsWith(".mp4"))
						mimeType = "video/mp4";
				}
				return mimeType;
			}
        }

		public WWWForm wwwForm
		{
			get
			{
				WWWForm form = new WWWForm();
				form.AddField("id", id);
				form.AddBinaryData("file", bytes, fileName, MimeType);

				return form;
			}
		}

		public UnityWebRequest unityWebRequest
		{
			get
			{
				UnityWebRequest request = null;
				switch (headerContentType)
                {
					case FormEnctype.APPLICATION_X_WWW_FORM_URLENCODED:
						request = UnityWebRequest.Post(url, wwwForm);
						request.SetRequestHeader("Content-Type", "application/json;charset=utf-8");
						break;
					case FormEnctype.MULTIPART_FORM_DATA:
						//分界线
						byte[] boundary = UnityWebRequest.GenerateBoundary();
						//结束分界线
						byte[] terminate = Encoding.UTF8.GetBytes(String.Concat("\r\n--", Encoding.UTF8.GetString(boundary), "--"));

						//Content-Type
						string contentType = String.Concat("multipart/form-data; boundary=", Encoding.UTF8.GetString(boundary));

						//表单
						List<IMultipartFormSection> form = new List<IMultipartFormSection>();
						form.Add(new MultipartFormFileSection("file", bytes, Path.GetFileName(fileName), MimeType));

						//序列化表单
						byte[] formSections = UnityWebRequest.SerializeFormSections(form, boundary);

						byte[] body = new byte[formSections.Length + terminate.Length];
						Buffer.BlockCopy(formSections, 0, body, 0, formSections.Length);
						Buffer.BlockCopy(terminate, 0, body, formSections.Length, terminate.Length);

						request = new UnityWebRequest(url, UnityWebRequest.kHttpVerbPOST);
						request.uploadHandler = (UploadHandler)new UploadHandlerRaw(body);
						request.uploadHandler.contentType = contentType;
						break;
				}

				request.timeout = 30;
				request.useHttpContinue = false;
				request.chunkedTransfer = false;

				return request;
			}
		}

		public void Dispose()
		{
			bytes = null;
			OnCompletedCallback = null;
			OnProgressCallback = null;
			OnErrorCallback = null;
		}
	}
}

Http请求


using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
/// <summary>
/// 与Web端交互
/// </summary>
public class HttpWebRequest : MonoBehaviour
{
	public static HttpWebRequest Instance { get; private set; }
	
	private void Awake()
    {
        DontDestroyOnLoad(gameObject);
        Instance = this;
    }

    // Delete请求
    public void Delete(string url, Action<string> completedCallback = null, Action<string> errorCallback = null)
    {
        StartCoroutine(DeleteRequest(url, completedCallback, errorCallback));
    }

    public IEnumerator DeleteRequest(string url, Action<string> completedCallback = null, Action<string> errorCallback = null)
    {
        yield return null;
        Debug.LogFormat("DELETE: {0}", url);
        UnityWebRequest request = DeleteUnityWebRequest(url);
        //yield return request.SendWebRequest(); //同步请求(请求完成后才会继续往下执行)
        request.SendWebRequest(); //异步请求

        while (!request.isDone)
            yield return new WaitForSeconds(0.1f);
        if (request.isHttpError || request.isNetworkError || request.responseCode != 200)
        {
            Debug.LogErrorFormat("DELETE Error\n{0}", request.error);
            if (errorCallback != null)
                errorCallback(request.error);
            yield break;//跳出协程
        }
        Debug.Log("DELETE 请求返回!");
        Debug.LogFormat("result={0}", request.downloadHandler.text);
        string json = request.downloadHandler.text;
        if (completedCallback != null)
            completedCallback(json);
    }
	
	// Get请求
    public void Get(string url, Action<string> completedCallback = null, Action<string> errorCallback = null)
    {
        StartCoroutine(GetRequest(url, completedCallback, errorCallback));
    }

    public IEnumerator GetRequest(string url, Action<string> completedCallback = null, Action<string> errorCallback = null)
    {
        yield return null;
        Debug.LogFormat("GET: {0}", url);
        UnityWebRequest request = GetUnityWebRequest(url);
        //yield return request.SendWebRequest(); //同步请求(请求完成后才会继续往下执行)
        request.SendWebRequest(); //异步请求

        while (!request.isDone)
            yield return new WaitForSeconds(0.1f);
        if (request.isHttpError || request.isNetworkError || request.responseCode != 200)
        {
            Debug.LogErrorFormat("GET Error\n{0}", request.error);
            if (errorCallback != null)
                errorCallback(request.error);
            yield break;//跳出协程
        }
        Debug.Log("GET 请求返回!");
        Debug.LogFormat("result={0}", request.downloadHandler.text);
        string json = request.downloadHandler.text;
        if (completedCallback != null)
            completedCallback(json);
    }

    // Post原始数据(即,非表单)
    public void Post(string url, string data, Action<string> completedCallback = null, Action<string> errorCallback = null)
    {
        StartCoroutine(PostRaw(url, data, completedCallback, errorCallback));
    }

    // Post原始数据(即,非表单)
    public IEnumerator PostRaw(string url, string data, Action<string> completedCallback = null, Action<string> errorCallback = null)
    {
        yield return null;
        Debug.LogFormat("POST: {0}\n{1}", url, data);
        byte[] postBytes = Encoding.UTF8.GetBytes(data);
        UnityWebRequest request = PostUnityWebRequest(url, data);
        //yield return request.SendWebRequest(); //同步请求(请求完成后才会继续往下执行)
        request.SendWebRequest(); //异步请求

        while (!request.isDone)
            yield return new WaitForSeconds(0.1f);
        if (request.isHttpError || request.isNetworkError || request.responseCode != 200)
        {
            Debug.LogErrorFormat("POST Error\n{0}", request.error);
            if (errorCallback != null)
                errorCallback(request.error);
            yield break;//跳出协程
        }
        Debug.Log("POST 请求返回!");
        Debug.LogFormat("result={0}", request.downloadHandler.text);
        string json = request.downloadHandler.text;
        if (completedCallback != null)
            completedCallback(json);
    }

    // GET UnityWebRequest
    public UnityWebRequest GetUnityWebRequest(string url)
    {
        DownloadHandler downloadHandler = new DownloadHandlerBuffer();
        UnityWebRequest request = new UnityWebRequest(url, UnityWebRequest.kHttpVerbGET);
        request.SetRequestHeader("Content-Type", "application/json");
        request.SetRequestHeader("Accept", "application/json");
        request.timeout = 10;
        request.useHttpContinue = false;
        request.chunkedTransfer = false;
        request.downloadHandler = downloadHandler;
        return request;
    }

    // POST UnityWebRequest
    public UnityWebRequest PostUnityWebRequest(string url, string postData)
    {
        byte[] postBytes = Encoding.UTF8.GetBytes(postData);
        DownloadHandler downloadHandler = new DownloadHandlerBuffer();
        UnityWebRequest request = new UnityWebRequest(url, UnityWebRequest.kHttpVerbPOST);
        request.SetRequestHeader("Content-Type", "application/json");
        request.SetRequestHeader("Accept", "application/json");
        request.timeout = 10;
        request.useHttpContinue = false;
        request.chunkedTransfer = false;
        request.downloadHandler = downloadHandler;
        request.uploadHandler = (UploadHandler)new UploadHandlerRaw(postBytes);
        return request;
    }

    // DELETE UnityWebRequest
    public UnityWebRequest DeleteUnityWebRequest(string url)
    {
        DownloadHandler downloadHandler = new DownloadHandlerBuffer();
        UnityWebRequest request = new UnityWebRequest(url, UnityWebRequest.kHttpVerbDELETE);
        request.SetRequestHeader("Content-Type", "application/json");
        request.SetRequestHeader("Accept", "application/json");
        request.timeout = 10;
        request.useHttpContinue = false;
        request.chunkedTransfer = false;
        request.downloadHandler = downloadHandler;
        return request;
    }
}


关于 CertificateHandler

UnityWebRequest request = new UnityWebRequest();
// Https 需要设置证书验证
request.certificateHandler = new AcceptAllCertificatesSignedWithASpecificKeyPublicKey();

using UnityEngine;
using UnityEngine.Networking;
using System.Security.Cryptography.X509Certificates;

/// <summary>
/// https://docs.unity3d.com/ScriptReference/Networking.CertificateHandler.ValidateCertificate.html
/// https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning#.Net
/// </summary>
public class AcceptAllCertificatesSignedWithASpecificKeyPublicKey : CertificateHandler
{
    // Encoded RSAPublicKey
    private static string PUB_KEY = "3082010A0282010100C3D57BDD8594A0E4948CF35B24B2A5CC3D7455E8DADAF9C410EE6CCD7DDD0CEB4A9A62D4E065AED004E0467107A93CAF69A7CAB61A57A306171213F39C3E601D621B144D8C97674A9753177713C3A9571D1821D8EAAF821E21F94F88658E2CB68EC7994B5130CD24C89813BDD19F7DDA331900D5C70310F65FC5624BC65EF6327F1EF74896B18A59FD34F095762F9B376D5F74D187ECA86D807CACF37A597E89B2A0E690C4146971FBEA641E61AFA28C0F58A453092DEA570BA405C720A77621711BCE1A902CEC13BCC34FAEFBD67E7C671F3A85883D2F6D583843F000B1FCCAA068C09FA5DEF69F800002D332A60549C7216B3FF929B2B562EF0E3E97B776E90203010001";

    //负责拒绝或接受在 https 请求上接收到的证书
    //注意:自定义证书验证目前仅针对以下平台实施 - Android、iOS、tvOS 和桌面平台
    //如果不需要验证,可以让这个方法直接返回true
    protected override bool ValidateCertificate(byte[] certificateData)
    {
        X509Certificate2 certificate = new X509Certificate2(certificateData);
        string pk = certificate.GetPublicKeyString();
        if (pk.Equals(PUB_KEY))
            return true;

        // Bad dog
        return false;
    }
}

示例:Post发送表单

private IEnumerator PostFormCoroutine(string url, WWWForm form)
	UnityWebRequest request = UnityWebRequest.Post(url, form);
	request.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded");
	request.timeout = 5;
	yield return request.SendWebRequest();
	if (request.result == UnityWebRequest.Result.ProtocolError || 
		request.result == UnityWebRequest.Result.ConnectionError ||
		request.result == UnityWebRequest.Result.DataProcessingError ||
		request.responseCode != 200)
	{
		Debug.LogErrorFormat("Http请求出错({0})\n{1}", request.responseCode, request.error);
		yield break; //跳出协程
	}
	string text = request.downloadHandler.text;
	Debug.Log(text); 
}  

示例:Post发送json

private IEnumerator PostJsonCoroutine(string url, string json, string token)
	UnityWebRequest request = new UnityWebRequest(url, UnityWebRequest.kHttpVerbPOST);
	byte[] data = Encoding.UTF8.GetBytes(json);
	request.uploadHandler = (UploadHandler)new UploadHandlerRaw(data);
	request.downloadHandler = new DownloadHandlerBuffer();
	request.SetRequestHeader("Content-Type", "application/json;charset=utf-8");
	//认证信息根据项目实际情况传参,这里仅作示范
	request.SetRequestHeader("Authorization", token);
	request.timeout = 5;
	yield return request.SendWebRequest();
	if (request.result == UnityWebRequest.Result.ProtocolError ||
		request.result == UnityWebRequest.Result.ConnectionError ||
		request.result == UnityWebRequest.Result.DataProcessingError ||
		request.responseCode != 200)
	{
		Debug.LogErrorFormat("Http请求出错({0})\n{1}", request.responseCode, request.error);
		yield break; //跳出协程
	}
	string text = request.downloadHandler.text;
	Debug.Log(text);
}  

注意,UnityWebRequest.Post()方法有bug,会使传到后台的json数据多个无效字符,导致json解析报错。


using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Networking;
/// <summary>
/// Web请求辅助类
/// Unity 2022+ 默认不支持Http请求,需要在 Project Settings 中开启
/// [Project Settings -> Player -> Allow downloads over HTTP* 设置为 Always allowed]
/// </summary>
public sealed class WebRequestHelper
{
    // 设置请求头
    private static void SetRequestHeader(UnityWebRequest request, Dictionary<string, string> header = null)
    {
        if (request == null)
           return;

        request.SetRequestHeader("Content-Type", "application/json;charset=utf-8");
        request.SetRequestHeader("Accept", "application/json");
        request.SetRequestHeader("Authorization", "");

        if (header == null)
           return;

        foreach (string key in header.Keys)
        {
           string value = header[key];
           if (value == null)
              continue;
           request.SetRequestHeader(key, value);
        }
    }

    // 解析
    private static void ParseAsync(UnityWebRequestAsyncOperation async, Action<string> completedCallback = null, Action<string> errorCallback = null)
    {
        string error = async.webRequest.error;
        if (!string.IsNullOrEmpty(error))
        {
            async.webRequest.Dispose();
            if (errorCallback == null)
                Debug.LogErrorFormat("请求出错: {0}", error);
            errorCallback?.Invoke(error);
        }
        else
        {
            string text = async.webRequest.downloadHandler.text;
            async.webRequest.Dispose();
            completedCallback?.Invoke(text);
        }
    }

    // 采用GET,向后端请求数据
    public static UnityWebRequestAsyncOperation Get(string url, Dictionary<string, string> header = null)
    {
        DownloadHandler downloadHandler = new DownloadHandlerBuffer();
        UnityWebRequest request = new UnityWebRequest(url, UnityWebRequest.kHttpVerbGET);
        request.downloadHandler = downloadHandler;
        SetRequestHeader(request, header);
        request.timeout = 5;
        request.chunkedTransfer = false;
        UnityWebRequestAsyncOperation async = request.SendWebRequest();
        return async;
    }

    public static IEnumerator GetAsync(string url, Dictionary<string, string> header = null, Action<string> completedCallback = null, Action<string> errorCallback = null, Action<float> progressCallback = null)
    {
        yield return null;
        UnityWebRequestAsyncOperation async = Get(url, header);
        while (!async.isDone)
        {
            progressCallback?.Invoke(async.progress);
            yield return new WaitForNextFrameUnit();
        }
        ParseAsync(async, completedCallback, errorCallback);
    }

    // 采用POST,向后端发送原始数据
    public static UnityWebRequestAsyncOperation Post(string url, byte[] rawData, Dictionary<string, string> header = null)
    {
        DownloadHandler downloadHandler = new DownloadHandlerBuffer();
        UploadHandler uploadHandler = new UploadHandlerRaw(rawData);
        UnityWebRequest request = new UnityWebRequest(url, UnityWebRequest.kHttpVerbPOST);
        request.downloadHandler = downloadHandler;
        request.uploadHandler = uploadHandler;
        SetRequestHeader(request, header);
        request.timeout = 5;
        UnityWebRequestAsyncOperation async = request.SendWebRequest();
        return async;
    }

    public static UnityWebRequestAsyncOperation Post(string url, string rawData, Dictionary<string, string> header = null)
    {
        byte[] postBytes = Encoding.UTF8.GetBytes(rawData);
        return Post(url, postBytes, header);
    }

    public static IEnumerator PostAsync(string url, string rawData, Dictionary<string, string> header, Action<string> completedCallback = null, Action<string> errorCallback = null, Action<float> progressCallback = null)
    {
        yield return null;
        UnityWebRequestAsyncOperation async = Post(url, rawData, header);
        while (!async.isDone)
        {
            progressCallback?.Invoke(async.progress);
            yield return new WaitForNextFrameUnit();
        }
        ParseAsync(async, completedCallback, errorCallback);
    }

    // 表单请求 POST
    public static IEnumerator PostFormAsync(string url, WWWForm form, Dictionary<string, string> header, Action<string> completedCallback = null, Action<string> errorCallback = null, Action<float> progressCallback = null)
    {
        yield return null;
        UnityWebRequest request = UnityWebRequest.Post(url, form);
        SetRequestHeader(request, header);
        UnityWebRequestAsyncOperation async = request.SendWebRequest();
        while (!async.isDone)
        {
            progressCallback?.Invoke(async.progress);
            yield return new WaitForNextFrameUnit();
        }
        ParseAsync(async, completedCallback, errorCallback);
    }

    //默认请求头
    public static Dictionary<string, string> GetDefaultRequestHeader()
    {
        Dictionary<string, string> header = new Dictionary<string, string>();
        header.Add("Content-Type", "application/json;charset=UTF-8");
        header.Add("Access-Control-Allow-0rigin", "*");
        header.Add("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE, PATCH");
        header.Add("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        return header;
    }

    // 异步加载文本
    public static IEnumerator LoadTextAsync(string url, Action<string> completedCallback = null, Action<string> errorCallback = null, Action<float> progressCallback = null)
    {
        using (UnityWebRequest webRequest = UnityWebRequest.Get(url))
        {
            webRequest.SendWebRequest();
            while (!webRequest.isDone)
            {
                progressCallback?.Invoke(webRequest.downloadProgress);
                yield return null;
            }
            if (webRequest.result == UnityWebRequest.Result.ConnectionError /*webRequest.isNetworkError*/
                || webRequest.result == UnityWebRequest.Result.ProtocolError/*webRequest.isHttpError*/)
            {
                Debug.LogErrorFormat("{0}\n{1}", webRequest.error.ToString(), url);
                errorCallback?.Invoke(webRequest.error);
            }
            else
            {
                var text = webRequest.downloadHandler.text;
                completedCallback?.Invoke(text);
            }
        }
    }

    // 异步加载图片
    public static IEnumerator LoadTextureAsync(string url, Action<Texture2D> completedCallback = null, Action<string> errorCallback = null, Action<float> progressCallback = null)
    {
        using (UnityWebRequest webRequest = UnityWebRequestTexture.GetTexture(url))
        {
            webRequest.SendWebRequest();
            while (!webRequest.isDone)
            {
                progressCallback?.Invoke(webRequest.downloadProgress);
                yield return null;
            }
            if (webRequest.result == UnityWebRequest.Result.ConnectionError /*webRequest.isNetworkError*/
                || webRequest.result == UnityWebRequest.Result.ProtocolError/*webRequest.isHttpError*/)
            {
                Debug.LogErrorFormat("{0}\n{1}", webRequest.error.ToString(), url);
                errorCallback?.Invoke(webRequest.error);
            }
            else
            {
                var texture = DownloadHandlerTexture.GetContent(webRequest);
                completedCallback?.Invoke(texture);
            }
        }
    }

    // 异步加载 AudioClip
    public static IEnumerator LoadAudioAsync(string url, Action<AudioClip> completedCallback = null, Action<string> errorCallback = null, Action<float> progressCallback = null)
    {
        string ext = Path.GetExtension(url).ToLower();
        AudioType audioType = AudioType.WAV;
        switch (ext)
        {
            case ".wav":
                audioType = AudioType.WAV;
                break;
            case ".mp3":
                audioType = AudioType.MPEG;
                break;
        }

        using (UnityWebRequest webRequest = UnityWebRequestMultimedia.GetAudioClip(url, audioType))
        {
            ((DownloadHandlerAudioClip)webRequest.downloadHandler).streamAudio = true;
            webRequest.SendWebRequest();
            while (!webRequest.isDone)
            {
                progressCallback?.Invoke(webRequest.downloadProgress);
                yield return null;
            }
            if (webRequest.result == UnityWebRequest.Result.ConnectionError /*webRequest.isNetworkError*/
                || webRequest.result == UnityWebRequest.Result.ProtocolError/*webRequest.isHttpError*/)
            {
                Debug.LogErrorFormat("{0}\n{1}", webRequest.error.ToString(), url);
                errorCallback?.Invoke(webRequest.error);
            }
            else
            {
                var audioClip = DownloadHandlerAudioClip.GetContent(webRequest);
                completedCallback?.Invoke(audioClip);
            }
        }
    }

    // 异步加载 AssetBundle
    public static IEnumerator LoadAssetBundleAsync(string url, Action<AssetBundle> completedCallback = null, Action<string> errorCallback = null, Action<float> progressCallback = null)
    {
        using (UnityWebRequest webRequest = UnityWebRequestAssetBundle.GetAssetBundle(url))
        {
            ((DownloadHandlerAssetBundle)webRequest.downloadHandler).autoLoadAssetBundle = false;
            webRequest.SendWebRequest();
            while (!webRequest.isDone)
            {
                progressCallback?.Invoke(webRequest.downloadProgress);
                yield return null;
            }
            if (webRequest.result == UnityWebRequest.Result.ConnectionError /*webRequest.isNetworkError*/
                || webRequest.result == UnityWebRequest.Result.ProtocolError/*webRequest.isHttpError*/)
            {
                Debug.LogErrorFormat("{0}\n{1}", webRequest.error.ToString(), url);
                errorCallback?.Invoke(webRequest.error);
            }
            else
            {
                var assetBundle = DownloadHandlerAssetBundle.GetContent(webRequest);
                completedCallback?.Invoke(assetBundle);
                assetBundle.Unload(false);
            }
        }
    }

    // 上传图片
    public static IEnumerator UploadTexture(string url, string filename, Dictionary<string, string> formField, Texture2D tex, Action<string> completedCallback = null, Action<string> errorCallback = null, Action<float> progressCallback = null)
    {
        yield return null;

        if (tex == null)
        {
            Debug.LogError("上传的 Texture=null");
            yield break;
        }

        if (string.IsNullOrEmpty(filename))
        {
            Debug.LogError("上传的 filename=null");
            yield break;
        }

        //如果在非主线程调用EncodeToJPG()会报以下错。
        //UnityException: EncodeToJPG can only be called from the main thread.
        byte[] bytes = tex.EncodeToJPG();
        WWWForm form = new WWWForm();
        form.headers["Content-Type"] = "image/jpeg";
        form.AddBinaryData("file", bytes, $"{filename}");
        //添加更多字段参数
        if (formField != null)
        {
            foreach (var key in formField.Keys)
            {
                string value = formField[key];
                if (!string.IsNullOrEmpty(value))
                    form.AddField(key, formField[key]);
            }
        }

        UnityWebRequest request = UnityWebRequest.Post(url, form);
        UnityWebRequestAsyncOperation async = request.SendWebRequest();
        while (!async.isDone)
        {
            progressCallback?.Invoke(async.progress);
            yield return new WaitForNextFrameUnit();
        }
        ParseAsync(async, completedCallback, errorCallback);
    }
}
评论:
发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容