Unity WebRequest GET-POST 简单封装

1. 关键代码

1.1 协程实现

using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public class WebRequest : MonoBehaviour
{
    /// <summary>
    /// GET请求
    /// </summary>
    /// <param name="url">请求地址</param>
    /// <param name="callback">请求完成回调</param>
    public void Get(string url, Action<bool,byte[]> callback)
    {
        StartCoroutine(CoroutineGetRequest(url, callback));
    }

     /// <summary>
    /// POST请求
    /// </summary>
    /// <param name="url">请求地址</param>
    /// <param name="postData">上传的数据</param>
    /// <param name="customHeaders">自定义请求头</param>
    /// <param name="callback">请求完成回调</param>
    public void Post(string url, string postData,Dictionary<string, string> customHeaders, Action<bool, byte[]> callback)
    {
        StartCoroutine(CoroutinePostRequest(url, postData, customHeaders, callback));
    }
     
     
    IEnumerator CoroutineGetRequest(string url,Action<bool,byte[]> callback)
    {
        // 使用UnityWebRequest发送一个GET请求
        using UnityWebRequest request = UnityWebRequest.Get(url);
        // 发送请求并等待结果
        yield return request.SendWebRequest();
        // 判断请求结果是否成功
        if (request.result != UnityWebRequest.Result.Success)
        {
            // 请求不成功,通过回调函数返回失败状态和错误信息
            callback?.Invoke(false, Encoding.UTF8.GetBytes(request.error));
        }
        else
        {
            // 获取响应消息
            byte[] responseMessage = request.downloadHandler.data;
            // 调用回调函数并传入true和响应消息
            callback?.Invoke(true, responseMessage);
        }
    }
     
    IEnumerator CoroutinePostRequest(string url, string postData, Dictionary<string, string> requestHeaders, Action<bool, byte[]> callback)
    {
        using (UnityWebRequest request = new UnityWebRequest(url, "POST"))
        {
            // 将POST数据转换为字节数组
            byte[] bodyRaw = System.Text.Encoding.UTF8.GetBytes(postData);
            // 设置上传处理程序为UploadHandlerRaw
            request.uploadHandler = new UploadHandlerRaw(bodyRaw);
            // 设置下载处理程序为DownloadHandlerBuffer
            request.downloadHandler = new DownloadHandlerBuffer();
            // 设置请求头的Content-Type
            request.SetRequestHeader("Content-Type", "application/json");

            // 添加自定义请求头
            if (requestHeaders != null)
            {
                foreach (var header in requestHeaders.Where(h => h.Key.ToLower() != "content-type"))
                {
                    request.SetRequestHeader(header.Key, header.Value);
                }
            }

            // 发送请求并等待结果
            yield return request.SendWebRequest();

            // 判断请求结果是否成功
            if (request.result != UnityWebRequest.Result.Success)
            {
                // 请求不成功,通过回调函数返回失败状态和错误信息
                callback?.Invoke(false, Encoding.UTF8.GetBytes(request.error));
            }
            else
            {
                // 请求成功,通过回调函数返回成功状态和响应消息
                var  responseMessage = request.downloadHandler.data;
                callback?.Invoke(true, responseMessage);
            }
        }
    }
}

1.2 异步实现

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;

public class AsyncWebRequest
{
    #region 异步请求
    /// <summary>
    /// 异步GET请求
    /// </summary>
    /// <param name="url"></param>
    /// <param name="requestComplete"></param>
    /// <returns></returns>
    public async void Get(string url, Action<bool, byte[]> requestComplete)
    {
        var result =await AsyncGetRequest(url);
        requestComplete?.Invoke(result.Item1, result.Item2);
    }
    
    private static async Task<(bool, byte[])> AsyncGetRequest(string url)
    {
        var tcs = new TaskCompletionSource<(bool, byte[])>();
        HttpClient client = new HttpClient();
        try
        {
            // 发送GET请求获取响应
            HttpResponseMessage response = await client.GetAsync(url);
            // 如果响应成功
            if (response.IsSuccessStatusCode)
            {
                // 读取响应体并设置结果为true和响应体
                byte[] responseBody = await response.Content.ReadAsByteArrayAsync();
                tcs.SetResult((true, responseBody));
            }
            // 如果响应失败
            else
            {
                // 设置结果为false和响应原因
                tcs.SetResult((false, null));
                Debug.LogError("请求失败");
            }
        }
        // 捕获所有异常并设置结果为false和异常消息
        catch (Exception ex)
        {
            Debug.LogError(ex);
            tcs.SetResult((false, null));
        }
        // 不管是否发生异常,最后都释放 HttpClient 的资源
        finally
        {
            client.Dispose();
        }
        // 返回异步任务的结果
        return await tcs.Task;
    }

    /// <summary>
    /// 异步POST请求
    /// </summary>
    /// <param name="url"></param>
    /// <param name="postData"></param>
    /// <param name="customHeaders"></param>
    /// <param name="requestComplete"></param>
    public async void Post(string url, string postData, Dictionary<string, string> customHeaders, Action<bool, byte[]> requestComplete = null)
    {
        var result = await AsyncPostRequest(url, postData, customHeaders);
        requestComplete?.Invoke(result.Item1, result.Item2);
    }
 
    private async Task<(bool, byte[])> AsyncPostRequest(string url, string postData, Dictionary<string, string> requestHeaders)
    {
        var tcs = new TaskCompletionSource<(bool, byte[])>();
        using (HttpClient client = new HttpClient())
        {
            try
            {
                // 创建StringContent对象时,显式设置Content-Type
                StringContent content = new StringContent(postData, Encoding.UTF8, "application/json");
 
                // 添加额外的请求头,但排除Content-Type
                if (requestHeaders != null)
                {
                    foreach (var header in requestHeaders.Where(h => h.Key.ToLower() != "content-type"))
                    {
                        client.DefaultRequestHeaders.Add(header.Key, header.Value);
                    }
                }
                // 发送POST请求
                HttpResponseMessage response = await client.PostAsync(url, content);
                
                // 判断请求是否成功
                if (response.IsSuccessStatusCode)
                {
                    var responseBody = await response.Content.ReadAsByteArrayAsync();
                    tcs.SetResult((true, responseBody));
                }
                else
                {
                    Debug.LogError($"请求失败,错误码: {(int)response.StatusCode}");
                    tcs.SetResult((false,  Encoding.UTF8.GetBytes(response.ReasonPhrase)));
                }
            }
            catch (Exception ex)
            {
                tcs.SetResult((false, Encoding.UTF8.GetBytes(ex.Message)));
            }
        }
        return await tcs.Task;
    }
}
    #endregion

2. 示例代码

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.UI;

public class Test : MonoBehaviour
{
    private WebRequest monoWebRequest;
    private AsyncWebRequest asyncWebRequest;
    public RawImage rawImage;

    private void Awake()
    {
        monoWebRequest = gameObject.AddComponent<WebRequest>();
        asyncWebRequest = new AsyncWebRequest();
    }

    // Start is called before the first frame update
    void Start()
    {
        //GetData();
        PostData();
    }

    private void GetData()
    {
        monoWebRequest.Get(
            "https://api.52starxi.cn/api/img-4k/img.php",
            (isComplete, result) =>
            {
                if (isComplete)
                {
                    // 请求格式为IMG 显示到 Image上
                    LoadImageFromBytes(result);
                    Debug.Log($"协程Get请求成功");
                }
                else
                {
                    Debug.LogError("协程Get请求失败");
                }
            });


        asyncWebRequest.Get(
            "https://v.api.aa1.cn/api/yiyan/index.php",
            (isComplete, result) =>
            {
                if (isComplete)
                {
                    Debug.Log($"异步Get请求成功:{Encoding.UTF8.GetString(result)}");
                }
                else
                {
                    Debug.LogError("异步Get请求失败");
                }
            });
    }


    private void PostData()
    {
        var postData = new 
        {
            title="测试邮件",
            nr="测试邮件内容",
            reveuser="123456@qq.com"
        };
        string body = JsonUtility.ToJson(postData);
        monoWebRequest.Post("http://api.paomotools.top/mail/email.php", body, null,
            (isComplete, result) =>
            {
                if (isComplete)
                {
                    Debug.Log($"协程Post请求成功:{Encoding.UTF8.GetString(result)}");
                }
                else
                {
                    Debug.LogError("协程Post请求失败");
                }
            });


        asyncWebRequest.Post(
            "http://api.paomotools.top/mail/email.php",
            body,
            null,
            (isComplete, result) =>
            {
                if (isComplete)
                {
                    Debug.Log($"异步Post请求成功:{Encoding.UTF8.GetString(result)}");
                }
                else
                {
                    Debug.LogError($"异步Post请求失败:{Encoding.UTF8.GetString(result)}");
                }
            });
    }


    private void LoadImageFromBytes(byte[] imageData)
    {
        StartCoroutine(LoadImageFromByteArray(imageData));
    }

    IEnumerator LoadImageFromByteArray(byte[] imageData)
    {
        // 创建一个新的Texture2D对象
        Texture2D texture = new Texture2D(2, 2); // 创建一个2x2的空纹理
        // 加载图片数据到Texture2D对象
        if (texture.LoadImage(imageData))
        {
            // 如果图片加载成功,设置RawImage的Texture
            rawImage.texture = texture;
        }
        else
        {
            Debug.LogError("Failed to load image from byte array.");
        }

        yield return null;
    }
}

3. 运行结果

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

今天喝水了嘛.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值