UnityWebRequest教程☀️2021,你还在使用过时的 www API吗?

简介: UnityWebRequest教程☀️2021,你还在使用过时的 www API吗?


🟥  常用网络传输方法

网络传输一般采用Get、Post、Put、Head,

同时还有一些控制的API,或者得到数据之类的API,那么就先从Get说起

1️⃣ Get下载数据

Get可用来下载字符串、数组、图片、AB包、音频等的数据。

当下载完成,可再将数据进行你想要的转换。

    void Start()
    {
        StartCoroutine(SendGetRequest());
    }
 
    IEnumerator SendGetRequest()
    {
        UnityWebRequest uwr = UnityWebRequest.Get("http://www.baidu.com");
        yield return uwr.SendWebRequest();
        if (uwr.isHttpError || uwr.isNetworkError)
        {
            Debug.Log(uwr.error);
        }
        else //请求成功
        {
            Debug.Log("Get:请求成功");
            Debug.Log("下载的数据:" + uwr.downloadedBytes);
        }
    }

 

2️⃣ Post上传数据

Post可以键值对的形式,将数据存在表单WWWForm里,

来上传字符串、图片、音频等的数据。

    void Start()
    {
        StartCoroutine(SendPostRequest());
    }
 
    IEnumerator SendPostRequest()
    {
        WWWForm form = new WWWForm();
        form.AddField("key", "value");
        form.AddField("name", "Chinar");
        UnityWebRequest webRequest = UnityWebRequest.Post("http://www.baidu.com", form);
 
        yield return webRequest.SendWebRequest();
        if (webRequest.isHttpError || webRequest.isNetworkError)
        {
            Debug.Log(webRequest.error);
        }
        else
        {
            Debug.Log("发送成功");
        }
    }

 

3️⃣ Put上传数据

UnityWebRequest数据传输,除了一般我们用的最多的Post、Get,其实还有Put、Head

Post 和 Put 确实很相像,通俗解释就是-------

新建一条记录的话就用post,

更新一条记录的话就用put.

但你用Post更新数据也没问题。

Put上传的东西跟Post相同,同样可以上传音视频、字符串等数据。

    void Start() {
        StartCoroutine(SendPutRequest());
    }
 
    //更新数据
    IEnumerator SendPutRequest() {
        byte[] myData = System.Text.Encoding.UTF8.GetBytes("This is some test data");
        UnityWebRequest www = UnityWebRequest.Put("http://www.my-server.com/upload", myData);
        yield return www.SendWebRequest();
 
        if(www.isNetworkError || www.isHttpError) {
            Debug.Log(www.error);
        }
        else {
            Debug.Log("Upload complete!");
        }
    }

 

4️⃣ Head下载头文件

Head跟Get类似,不同的是Head不会下载文件,只会得到头文件数据。

你可以先了解到这个文件的大小等信息,再让用户决定怎样操作。

使用方法:见下方的 “获取要下载数据的长度”。

 

 

🟧 网络传输的API

有些人又要说了,那我会传输方法了,那怎样怎样得到传输速度呢?

本段就开始讲解UnityWebRequest的各个实用的方法,或者API

1️⃣ 测试网址是否连通

    void Start()
    {
        StartCoroutine(SendRequest());
    }
 
    //测试网址是否连通
    IEnumerator SendRequest()
    {
        Uri uri = new Uri("http://www.baidu.com");
        UnityWebRequest uwr = new UnityWebRequest(uri);
        //等待时间(秒)  超过此数值时,UnityWebReqest的尝试连接将终止
        uwr.timeout = 5;
        yield return uwr.SendWebRequest();
        if (uwr.isHttpError || uwr.isNetworkError)
        {
            Debug.LogError("请求失败:" + uwr.error);
        }
        else //请求成功
        {
            Debug.Log("请求成功");
        }
    }

 

2️⃣ 获取要下载数据的长度

这个API通常用在要下载文件时,先显示要下载文件的大小。

比如《炉石》的是否更新界面、《和平精英》的新场景资源包界面

使用Head的好处是,Head会得到要下载数据的头文件,却不会下载文件。

    void Start()
    {
        StartCoroutine(SendHeadRequest());
    }
 
    private IEnumerator SendHeadRequest(string url)
    {
        UnityWebRequest huwr = UnityWebRequest.Head(url);
        yield return huwr.SendWebRequest();
        if (huwr.isNetworkError || huwr.isHttpError) //如果出错
        {
            Debug.Log(huwr.error); //输出 错误信息
        }
        else
        {
            long totalLength = long.Parse(huwr.GetResponseHeader("Content-Length"));
            print("文件的长度:"+totalLength);
        }
    }

 

3️⃣ 显示下载进度

    public void Start()
    {
        StartCoroutine(DownloadFile());
    }
    
    IEnumerator DownloadFile()
    {
        UnityWebRequest uwr = UnityWebRequest.Get("http://dpv.videocc.net/689be7713e/1/689be7713e7898052861311bd74fc831_3.mp4?pid=1611569020809X1563841");
        uwr.SendWebRequest();
 
        if (uwr.isNetworkError || uwr.isHttpError)
        {
            Debug.Log(uwr.error);
        }
        else
        {
            while (!uwr.isDone)
            {
                GetComponent<Slider>().value = uwr.downloadProgress;
                //Math.floor() 返回小于或等于一个给定数字的最大整数。
                GetComponent<Text>().text = Math.Floor(uwr.downloadProgress * 100) + "%";
                yield return 0;
            }
 
            if (uwr.isDone) //如果下载完成了
            {
                GetComponent<Slider>().value = 1; //改变Slider的值
                GetComponent<Text>().text = 100 + "%";
            }
        }
    }

注意哈,


我们跟上面的Get相比,要注意这儿就没有yield return webRequest.SendWebRequest()了,

而是直接 webRequest.SendWebRequest()

因为yield return后,是直接下载完成或者下载失败。但我们在这儿不需要等待,我们需要时刻知道下载进度。

 

4️⃣ 显示上传进度

跟下载进度类似,是将downloadProgress,变成了uploadProgress。

void Start()
    {
        StartCoroutine(SendPostRequest());
    }
 
    IEnumerator SendPostRequest()
    {
        WWWForm form = new WWWForm();
        form.AddField("key", "value");
        form.AddField("name", "Chinar");
        UnityWebRequest webRequest = UnityWebRequest.Post("http://www.baidu.com", form);
        
        webRequest.SendWebRequest();
            
        if (webRequest.isNetworkError || webRequest.isHttpError)
        {
            Debug.Log(webRequest.error);
        }
        else
        {
            while (!webRequest.isDone)
            {
                GetComponent<Slider>().value = webRequest.uploadProgress;
                //Math.floor() 返回小于或等于一个给定数字的最大整数。
                GetComponent<Text>().text = Math.Floor(webRequest.uploadProgress * 100) + "%";
                yield return 0;
            }
 
            if (webRequest.isDone) //如果下载完成了
            {
                GetComponent<Slider>().value = 1; //改变Slider的值
                GetComponent<Text>().text = 100 + "%";
            }
        }
    }

 

 

5️⃣ 保存下载的文件

...
byte[] results = uwr.downloadHandler.data;
// 注意真机上要用Application.persistentDataPath
CreateFile(Application.streamingAssetsPath + "/MP4/test.mp4", results, uwr.downloadHandler.data.Length);
AssetDatabase.Refresh(); //刷新一下
...
 
    void CreateFile(string path, byte[] bytes, int length)
    {
        FileInfo file = new FileInfo(path);
        if (file.Exists)
            return;
        
        Stream sw;
        sw = file.Create();
        sw.Write(bytes, 0, length);
        sw.Close();
        sw.Dispose();
    }

 

 

6️⃣ 断点续传

断点续传的机制是通过Head先知道要下载文件的大小,然后Get进行下载。

若点了暂停下载,实际是通过break,取消了下载的StartCoroutine。再次开始下载是再次调用StartCoroutine下载。

但再次下载,会先检测本地文件的长度,然后将该长度传入下载请求,从该长度处后开始下载、写入文件,完成断点续传。

    public Button downloadBtn; //开始下载按钮
    public Button controBtn; //暂停下载与恢复下载按钮
 
    private string Url = "http://dpv.videocc.net/689be7713e/1/689be7713e7898052861311bd74fc831_3.mp4?pid=1611569020809X1563841";
    private bool _isPause;
 
    void Start()
    {
        downloadBtn.onClick.AddListener(StartDownload);
        controBtn.onClick.AddListener(DownLoadCon);
    }
 
    public void DownLoadCon()
    {
        if (_isPause)
        {
            _isPause = false;
            Debug.Log("当前继续开始下载");
            StartDownload();
        }
        else
        {
            _isPause = true;
            Debug.Log("当前已暂停下载");
        }
    }
 
    private void StartDownload()
    {
        // 注意真机上要用Application.persistentDataPath
        StartCoroutine(DownloadFile(Url, Application.streamingAssetsPath + "/MP4/test.mp4"));
    }
 
    private IEnumerator DownloadFile(string url, string filePath)
    {
        UnityWebRequest huwr = UnityWebRequest.Head(url);
        yield return huwr.SendWebRequest();
        if (huwr.isNetworkError || huwr.isHttpError)
        {
            Debug.Log(huwr.error);
        }
        else
        {
            long totalLength = long.Parse(huwr.GetResponseHeader("Content-Length"));
            print("文件的全部长度:" + totalLength);
 
            string dirPath = Path.GetDirectoryName(filePath);
            if (!Directory.Exists(dirPath)) //判断路径是否存在
            {
                Directory.CreateDirectory(dirPath);
            }
 
            //创建一个文件流,指定路径为filePath,模式为打开或创建,访问为写入
            using (FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write))
            {
                long nowFileLength = fs.Length; //当前本地的文件长度
                if (nowFileLength < totalLength)
                {
                    // FileStream.Seek:从当前文件一开始,向后移动nowFileLength个字节,将该流的当前位置设置为给定值。
                    fs.Seek(nowFileLength, SeekOrigin.Begin);
                    UnityWebRequest uwr = UnityWebRequest.Get(url); //创建UnityWebRequest对象,将Url传入
                    uwr.SetRequestHeader("Range", "bytes=" + nowFileLength + "-" + totalLength);
                    uwr.SendWebRequest();
 
                    if (uwr.isNetworkError || uwr.isHttpError)
                    {
                        Debug.Log(uwr.error);
                    }
                    else
                    {
                        long index = 0;
                        while (nowFileLength < totalLength) //只要下载没有完成,一直执行此循环
                        {
                            print(nowFileLength);
                            if (_isPause)    //暂停下载
                                break;
                            yield return null;
                            byte[] data = uwr.downloadHandler.data;
                            if (data != null)
                            {
                                long length = data.Length - index;
                                fs.Write(data, (int) index, (int) length);
                                index += length;
                                nowFileLength += length;
                                if (nowFileLength >= totalLength)
                                {
                                    print("下载完成!");
                                    AssetDatabase.Refresh();
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
    }

小提示:

FileStream.Seek(long offset, SeekOrigin origin):有两个参数。第一参数规定文件指针以字节为单位移动的距离。第二个规定开始计算的位置

SeekOrigin是一个枚举,包含三个值:Begin、Current、End。

  • aFile.Seek(8,SeekOrigin.Begin)---------将文件的指针移动到第八个字节。起始位置就是文件的第一个字节
  • aFile.Seek(-5,SeekOrigin.End); 从文件的末尾向前查找五个字节
  • aFile.Seek(2,SeekOrigin.Current);
相关文章
|
6月前
|
人工智能 数据可视化 测试技术
Postman 性能测试教程:快速上手 API 压测
本文介绍API上线后因高频调用导致服务器告警,通过Postman与Apifox进行压力测试排查性能瓶颈。对比两款工具在批量请求、断言验证、可视化报告等方面的优劣,探讨API性能优化策略及行业未来发展方向。
Postman 性能测试教程:快速上手 API 压测
|
8月前
|
JSON API 网络安全
通用邮箱邮件获取API教程:支持IMAP/POP3协议
本文介绍如何通过接口盒子的免费API获取邮箱邮件,支持IMAP/POP3协议,适用于QQ邮箱、网易邮箱等主流服务。内容包括接口基本信息、请求参数、返回参数、调用示例及注意事项,帮助开发者快速实现邮件读取功能。
1101 7
|
8月前
|
JSON 监控 API
在线网络PING接口检测服务器连通状态免费API教程
接口盒子提供免费PING检测API,可测试域名或IP的连通性与响应速度,支持指定地域节点,适用于服务器运维和网络监控。
1180 0
|
8月前
|
JSON API PHP
通用图片搜索API:百度源免费接口教程
本文介绍一款基于百度图片搜索的免费API接口,由接口盒子提供。支持关键词搜索,具备详细请求与返回参数说明,并提供PHP及Python调用示例。开发者可快速集成实现图片搜索功能,适用于内容聚合、素材库建设等场景。
1191 0
|
8月前
|
JSON 机器人 API
随机昵称网名API接口教程:轻松获取百万创意昵称库
接口盒子提供随机昵称网名API,拥有百万级中文昵称库,支持聊天机器人、游戏角色等场景的昵称生成。提供详细调用指南及多语言示例代码,助力开发者高效集成。
769 0
|
6月前
|
人工智能 API 开发者
图文教程:阿里云百炼API-KEY获取方法,亲测全流程
本文详细介绍了如何获取阿里云百炼API-KEY,包含完整流程与截图指引。需先开通百炼平台及大模型服务,再通过控制台创建并复制API-KEY。目前平台提供千万tokens免费额度,适合开发者快速上手使用。
5410 5
|
8月前
|
JSON API PHP
天气预报免费API接口【地址查询版】使用教程
本文介绍了如何使用中国气象局官方数据提供的免费天气预报API接口,通过省份和地点查询指定地区当日天气信息。该接口由接口盒子支持,提供JSON格式数据、GET/POST请求方式,并需注册获取用户ID和KEY进行身份验证。
4520 2
|
8月前
|
JSON Shell API
查手机号归属地免费API接口教程
本接口提供手机号码归属地查询功能,支持获取号段、归属地省份/城市、运营商、区号、邮编等信息。请求地址为 `https://cn.apihz.cn/api/ip/shouji.php`,支持 POST 或 GET 方式调用,需提供 `id`、`key` 和 `phone` 参数。返回包含归属地信息及运营商等数据,适用于手机号归属查询场景。
1551 6
|
8月前
|
JSON API PHP
ICP备案查询免费API接口使用教程
本文介绍如何通过接口盒子提供的免费API接口查询域名ICP备案信息,包含请求地址、参数说明及PHP和Python调用示例,适用于开发者快速集成备案查询功能。
598 1