BestHttpV3 实例代码,使用besthttp发送请求

BestHttpV3 实例代码

The world is changing, and I’m just trying to keep up. ----Arthur Morgan

实现功能:

  1. 发送请求
  2. 下载图片保存_阻塞式
  3. 下载图片保存——轮询式
  4. 下载小文件(图片),不保存
  5. 发送表单文件

插件导入

UniTask

https://github.com/Cysharp/UniTask

BestHttp v3,这个插件有v1,v2,v3版本,每个版本的文档都不相同!

https://assetstore.unity.com/packages/tools/network/best-http-267636

在这里插入图片描述

参考文档

//快速开始
//https://bestdocshub.pages.dev/HTTP/getting-started/#1-create-request

//BestHttp 总文档
//https://bestdocshub.pages.dev/

//测试网站
//httpbin.org

//文件下载部分的文档
//https://bestdocshub.pages.dev/HTTP/getting-started/downloads/#progress-tracking

//BestHttp v1的文档(过时)
//https://besthttp-documentation.readthedocs.io/en/dev/1.HTTP/HTTPRequest/

最佳实践代码

using Best.HTTP;
using Best.HTTP.Request.Upload.Forms;
using Best.HTTP.Response;
using Best.HTTP.Shared.PlatformSupport.Memory;
using Cysharp.Threading.Tasks;
using System;
using System.Buffers;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using UnityEngine;

public class BestHttp_ECode : MonoBehaviour
{
    string tmp_postURL = "http://www.baidu.com";

    private string path_bigFilePatg = "http://n.sinaimg.cn/sinacn/w480h306/20180118/6452-fyqtwzu4786357.jpg";

    private string path_imageURL = "http://n.sinaimg.cn/sinacn/w480h306/20180118/6452-fyqtwzu4786357.jpg";

    void Start()
    {
        StartCoroutine(nameof(Test_Get));
        StartCoroutine(nameof(ShowPictureByHttpRequest));
        StartCoroutine(nameof(Test_SendPost));


        StartCoroutine(nameof(DownBigFile_WithBlicking));
        StartCoroutine(nameof(Test_DownLoadABigFile_WithPolling));
    }


    private IEnumerator Test_Get()
    {
        HTTPRequest httpRequest = new HTTPRequest(new System.Uri(tmp_postURL), HTTPMethods.Get
           , (request, response) =>
           {
               if (response.IsSuccess)
               {
                   Debug.Log(response.DataAsText);
               }
               else
               {
                   Debug.Log("发送失败");
               }
           });
        httpRequest.Send();
        yield return null;
    }


    /// <summary>
    ///  Post测试方法
    /// </summary>
    private IEnumerator Test_SendPost()
    {
        HTTPRequest tmp_post = new HTTPRequest(new System.Uri(tmp_postURL), HTTPMethods.Post,
            (request, response) => { Debug.Log(response.DataAsText); });

        yield return tmp_post.Send();
    }

    private IEnumerator AddFormData()
    {
        HTTPRequest tmp_post = new HTTPRequest(new System.Uri(tmp_postURL), HTTPMethods.Post, RequestFinishedCallback);

        tmp_post.UploadSettings.UploadStream = new MultipartFormDataStream()
                 .AddField("Field Name 1", "Field value 1")
            .AddField("Field Name 2", "Field value 2");

        MultipartFormDataStream tmp_mfds = new MultipartFormDataStream();
        tmp_mfds.AddField("ddd", "qqqq");

        tmp_post.UploadSettings.UploadStream = tmp_mfds;
        yield return tmp_post.Send();
    }

    // 4. This callback is called when the request is finished. It might finished because of an error!
    private void RequestFinishedCallback(HTTPRequest req, HTTPResponse resp)
    {
        switch (req.State)
        {
            case HTTPRequestStates.Finished:
                if (resp.IsSuccess)
                {
                    Debug.Log("Upload finished succesfully!");
                }
                else
                {
                    Debug.Log($"Server sent an error: {resp.StatusCode}-{resp.Message}");
                }
                break;

            default:
                Debug.LogError($"Request finished with error! Request state: {req.State}");
                break;
        }
    }

    private IEnumerator StartHttpRequestsByCoroutine()
    {
        // 1. Create request
        var request = HTTPRequest.CreatePost("https://httpbin.org/post");

        // 2. Setup
        request.UploadSettings.UploadStream = new MultipartFormDataStream()
            .AddField("Field Name 1", "Field value 1")
            .AddField("Field Name 2", "Field value 2");

        // 3. Send
        request.Send();

        // 4. Wait for completion
        yield return request;

        switch (request.State)
        {
            case HTTPRequestStates.Finished:
                // 5. Process response
                if (request.Response.IsSuccess)
                {
                    Debug.Log("Upload finished succesfully!");
                }
                else
                {
                    // 6. Error handling
                    Debug.LogError($"Server sent an error: {request.Response.StatusCode}-{request.Response.Message}");
                }
                break;

            // 6. Error handling
            default:
                Debug.LogError($"Request finished with error! Request state: {request.State}");
                break;
        }
    }

    /// <summary>
    /// 异步发送http请求
    /// </summary>
    /// <returns></returns>
    private async UniTask SendRqeustAsync()
    {
        // 1. Create request
        var request = HTTPRequest.CreatePost("https://httpbin.org/post");

        // 2. Setup
        request.UploadSettings.UploadStream = new MultipartFormDataStream()
            .AddField("Field Name 1", "Field value 1")
            .AddField("Field Name 2", "Field value 2");

        try
        {
            // 3. Send & wait for completion
            var response = await request.GetHTTPResponseAsync();
            // 5. Process response
            if (response.IsSuccess)
            {
                Debug.Log("Upload finished succesfully!");
            }
            else
            {
                Debug.LogError($"Server sent an error: {response.StatusCode}-{response.Message}");
            }
        }
        catch (AsyncHTTPException e)
        {
            // 6. Error handling
            Debug.LogError($"Request finished with error! Error: {e.Message}");
        }
    }

    /// <summary>
    /// 异步发送http请求获取AB包_
    /// GetAssetBundleAsync, GetAsStringAsync, 
    /// GetAsTexture2DAsync, GetRawDataAsync,
    /// GetFromJsonResultAsync<T> 
    /// </summary>
    /// <returns></returns>
    private async UniTask SendRqeustGetABPackageAsync()
    {
        // 1. Create request
        var request = HTTPRequest.CreatePost("https://httpbin.org/post");

        // 2. Setup
        request.UploadSettings.UploadStream = new MultipartFormDataStream()
            .AddField("Field Name 1", "Field value 1")
            .AddField("Field Name 2", "Field value 2");

        try
        {
            // 3. Send & wait for completion
            var response = await request.GetAssetBundleAsync();
            // 5. Process response
            if (response != null)
            {
                Debug.Log("Upload finished succesfully!");
                Debug.Log("AB包下载完毕");
            }
            else
            {
                Debug.Log("ab包下载失败");
            }
        }
        catch (AsyncHTTPException e)
        {
            // 6. Error handling
            Debug.LogError($"Request finished with error! Error: {e.Message}");
        }

    }

    //Even if the request's State is HTTPRequestStates.Finished, the server might sent an error and the response's content isn't what we expect! By testing the response's StatusCode or checking IsSuccess we can make sure that all possibilities are handled.
    //即使请求的 State 为 HTTPRequestStates.Finished,服务器也可能会发送错误,并且响应的内容不是我们所期望的!
    //通过测试响应的 StatusCode 或检查 IsSuccess,我们可以确保处理所有可能性。





    //对于较小的资源,HTTPResponse类提供了一些专门的属性:byte[]Data、字符串DataAsText和Texture2D DataAsTexture2D。这些可用于访问作为原始字节、转换为utf-8字符串或Unity Texture2D的下载数据。
    /// <summary>
    /// 通过HttpRequest显示图片
    /// </summary>
    private IEnumerator ShowPictureByHttpRequest()
    {
        GameObject tmp_Plane = GameObject.CreatePrimitive(PrimitiveType.Plane);
        tmp_Plane.name = "tmp_Plane";
        tmp_Plane.transform.position = Vector3.zero;
        new HTTPRequest(new System.Uri(path_imageURL),
            (request, response) =>
            {
                var tex = new Texture2D(0, 0);
                tex.LoadImage(response.Data);
                //System.IO.File.WriteAllBytes("path", response.Data);//保存到本地

                tmp_Plane.GetComponent<Renderer>().material.mainTexture = tex;
                //tmp_Plane.GetComponent<Renderer>().material.mainTexture = response.DataAsTexture2D;//直接加载图片,不自己转换


            }).Send();
        yield return null;
    }

    /// <summary>
    /// 使用轮询进行流式处理
    /// </summary>
    /// <returns></returns>
    private IEnumerator Test_DownLoadABigFile_WithPolling()
    {
        var request = new HTTPRequest(new Uri(path_bigFilePatg), HTTPMethods.Get);
        request.DownloadSettings.OnDownloadStarted += OnBigFileDownloadStarted;
        request.DownloadSettings.OnDownloadProgress += OnDownloadProgress;

        void OnDownloadProgress(HTTPRequest req, long progress, long length)
            => Debug.Log($"{progress:N0}/{length:N0}");

        yield return request.Send();
    }


    /// <summary>
    /// 当大文件开始下载的时候_轮询进行流处理
    /// </summary>
    /// <param name="req"></param>
    /// <param name="resp"></param>
    /// <param name="stream"></param>
    private void OnBigFileDownloadStarted(HTTPRequest req, HTTPResponse resp, DownloadContentStream stream)
    {
        //只有当响应的状态代码为2xx时,才会调用此事件,并且不会针对重定向、请求和服务器错误(4xx和5xx状态代码)进行调用。进一步减少您必须处理的边缘情况数量和必须管理的代码复杂性。
        Debug.Log("Download Started");

        StartCoroutine(ParseContent(stream));

    }

    /// <summary>
    /// 轮询进行流处理
    /// </summary>
    /// <param name="stream"></param>
    /// <returns></returns>
    IEnumerator ParseContent(DownloadContentStream stream)
    {
        string filePath = Path.Combine(Application.streamingAssetsPath, "downloadedFile.png");
        using (FileStream fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
        {
            try
            {
                while (!stream.IsCompleted)
                {
                    // Try to take out a download segment from the Download Stream.
                    if (stream.TryTake(out var buffer))
                    {
                        // 将数据写入文件
                        fileStream.Write(buffer.Data, 0, buffer.Data.Length);

                        // Make sure that the buffer is released back to the BufferPool.
                        BufferPool.Release(buffer);
                    }

                    yield return null;
                }
            }
            finally
            {
                // Don't forget to Dispose the stream!
                stream.Dispose();
                // 下载本身始终在非 Unity 主线程上完成,它不会影响正在运行的游戏逻辑和渲染!
            }
        }
        Debug.Log($"File saved to: {filePath}");
    }


    /// <summary>
    /// 使用阻塞式下载大文件
    /// </summary>
    private void DownBigFile_WithBlicking()
    {
        var request = HTTPRequest.CreateGet(path_imageURL, OnRequestFinishedCallack_WithBlocking);

        request.DownloadSettings.OnDownloadStarted += OnDownloadStarted_WithBlocking;
        request.DownloadSettings.DownloadStreamFactory = (req, resp, bufferAvailableHandler)
            => new BlockingDownloadContentStream(resp, req.DownloadSettings.ContentStreamMaxBuffered, bufferAvailableHandler);

        request.DownloadSettings.OnDownloadProgress += OnDownloadProgress;

        void OnDownloadProgress(HTTPRequest req, long progress, long length)
            => Debug.Log($"{progress:N0}/{length:N0}");

        request.Send();

    }


    private void OnRequestFinishedCallack_WithBlocking(HTTPRequest req, HTTPResponse resp)
    {

        Debug.Log("下载本身始终在非 Unity 主线程上完成,它不会影响正在运行的游戏逻辑和渲染!");

    }

    private async void OnDownloadStarted_WithBlocking(HTTPRequest req, HTTPResponse resp, DownloadContentStream stream)
    {
        //StartCoroutine();
        UniTask<byte[]> downloadedData_unitask = await Task.Run(() => ConsumeDownloadStream(stream as BlockingDownloadContentStream));
        byte[] downloadedData = await downloadedData_unitask;

        string filePath = Path.Combine(Application.streamingAssetsPath, "downloadedFile2.png");
        await SaveFileAsync(filePath, downloadedData);
    }
    private async UniTask SaveFileAsync(string filePath, byte[] data)
    {
        // 确保目录存在
        Directory.CreateDirectory(Path.GetDirectoryName(filePath));

        // 将字节数组写入文件
        using (FileStream fs = new FileStream(filePath, FileMode.Create))
        {
            await fs.WriteAsync(data, 0, data.Length);
        }

        Debug.Log($"File saved to: {filePath}");
    }

    public async UniTask<Byte[]> ConsumeDownloadStream(BlockingDownloadContentStream blockingStream)
    {
        List<Byte[]> segments = new List<Byte[]>();
        try
        {
            while (!blockingStream.IsCompleted)
            {
                // Take out a segment from the downloaded
                if (blockingStream.TryTake(out var buffer))
                {
                    try
                    {
                        // Save the segment for later concatenation
                        Byte[] segment = new Byte[buffer.Count];
                        Array.Copy(buffer.Data, buffer.Offset, segment, 0, buffer.Count);
                        segments.Add(segment);
                    }
                    finally
                    {
                        // Return the buffer to the pool
                        ArrayPool<byte>.Shared.Return(buffer.Data);
                    }
                }
            }
        }
        finally
        {
            blockingStream.Dispose();
        }

        // Concatenate all segments into one array
        int totalLength = segments.Sum(s => s.Length);
        Byte[] result = new Byte[totalLength];

        int offset = 0;
        foreach (var segment in segments)
        {
            Array.Copy(segment, 0, result, offset, segment.Length);
            offset += segment.Length;
        }
        return result;

    }

}

在这里插入图片描述

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值