using System;
using System.Collections;
using System.IO;
using UnityEditor;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
public class UnityWebRequestDemo : MonoBehaviour
{
/*
* 一.概述
* UnityWebRequest支持与上传,下载及断点续传功能。
* UnityWebRequest由三个元素组成:
* 1. UploadHandler 处理数据将数据上传到服务器的对象
* 2. DownloadHandler 从服务器下载数据的对象
* 3. UnityWebRequest 负责与Http进行通信并管理上面两个对象
*
* 常用的方法:
* SendWebRequest():开始与远程服务器通信。在调用此方法之后,有必要的话UnityWebRequest将执行DNS解析,将HTTP请求发送到目标URL的远程服务器并处理服务器的响应
* Get(url): 创建一个HTTP为传入URL的UnityWebRequest对象
* Post(url): 向Web服务器发送表单信息
* Put(url): 将数据上传到Web服务器
* Abort(): 直接结束联网
* Head(): 创建一个为传输Http头请求的UnityWebRequest对象
* GetResponseHeader(): 返回一个字典,内容为在最新的HTTP响应中收到的所有响应头
*/
/*
* 二.构造函数
* public UnityWebRequest();
* public UnityWebRequest(Uri uri);
* public UnityWebRequest(Uri uri,string method);
* public UnityWebRequest(Uri uri,string method,Networking.DownloadHandler downloadHandler,Networking.UploadHandler uploadHandler);
* 参数含义:
* method:相当于方法,只有GET、POST、PUT、HEAD四种,默认为GET,一旦调用SendWebRequest(),就无法更改
* downloadHandler:下载数据的委托方法
* uploadHandler:上传数据的委托方法
*/
private void Start()
{
// Get();
// Post();
// Put();
// Head();
// GetResponseHeader();
// DownLoadFile();
// BreakpointDownload();
}
#region GET
/*
* Get方法,创建一个 UnityWebReqest对象,参数传入URL。
*/
void Get()
{
StartCoroutine(SendRequest_Get());
}
IEnumerator SendRequest_Get()
{
UnityWebRequest unityWebRequest = UnityWebRequest.Get("http://www.baidu.com"); //创建UnityWebRequest对象
yield return unityWebRequest.SendWebRequest(); //等待返回请求的信息
if (unityWebRequest.result == UnityWebRequest.Result.ProtocolError ||
unityWebRequest.result == UnityWebRequest.Result.ConnectionError) //如果其 请求失败,或是 网络错误
{
Debug.Log(unityWebRequest.error); //打印错误原因
}
else //请求成功
{
Debug.Log("Get:请求成功");
//如果访问的链接有返回文本结果,比如json文本,则通过text获取
string result = unityWebRequest.downloadHandler.text;
Debug.Log(result);
//如果访问的是资源链接,比如图片,则通过data拿到图片二进制流
//byte[] data = uwr.downloadHandler.data;
}
}
#endregion
#region POST
/*
* Post方法将一个表上传到远程的服务器,一般来说我们登陆某个网站的时候会用到这个方法,我们的账号密码会以一个表单的形式传过去。
*/
void Post()
{
StartCoroutine(SendRequest_Post());
}
IEnumerator SendRequest_Post()
{
WWWForm form = new WWWForm();
//键值对
form.AddField("key", "value");
form.AddField("name", "Chinar");
//请求链接,并将form对象发送到远程服务器
UnityWebRequest webRequest = UnityWebRequest.Post("http://www.baidu.com", form);
yield return webRequest.SendWebRequest();
if (webRequest.result == UnityWebRequest.Result.ProtocolError ||
webRequest.result == UnityWebRequest.Result.ConnectionError) //如果其 请求失败,或是 网络错误
{
Debug.Log(webRequest.error);
}
else
{
Debug.Log("发送成功");
}
}
#endregion
#region PUT
/*
* Put方法将数据发送到远程的服务器。
*/
void Put()
{
StartCoroutine(SendRequest_Put());
}
IEnumerator SendRequest_Put()
{
byte[] myData = System.Text.Encoding.UTF8.GetBytes("Chinar的测试数据");
using (UnityWebRequest webRequest = UnityWebRequest.Put("http://www.baidu.com", myData))
{
yield return webRequest.SendWebRequest();
if (webRequest.result == UnityWebRequest.Result.ProtocolError ||
webRequest.result == UnityWebRequest.Result.ConnectionError) //如果其 请求失败,或是 网络错误
{
Debug.Log(webRequest.error);
}
else
{
Debug.Log("上传成功!");
}
}
}
#endregion
#region HEAD
void Head()
{
StartCoroutine(SendRequest_Head());
}
IEnumerator SendRequest_Head()
{
UnityWebRequest webRequest =
UnityWebRequest.Head("http://www.chinar.xin/chinarweb/WebRequest/Get/00-效果.mp4"); //创建UnityWebRequest对象
yield return webRequest.SendWebRequest(); //等待返回请求的信息
if (webRequest.result == UnityWebRequest.Result.ProtocolError ||
webRequest.result == UnityWebRequest.Result.ConnectionError) //如果其 请求失败,或是 网络错误
{
Debug.Log(webRequest.error); //打印错误原因
}
else //请求成功
{
Debug.Log("Head:请求成功");
}
}
#endregion
#region Abort
/*
* Abort方法会尽快结束联网,可以随时调用此方法。
*如果 UnityWebRequest尚未完成,那么 UnityWebRequest将尽快停止上传或下载数据。 中止的 UnityWebRequests被认为遇到了系统错误 。
*isNetworkError或isHttpError属性将返回true,error属性将为“User Aborted”。
*/
#endregion
#region GetResponseHeader
/*
* GetResponseHeader方法可以用来获取请求文件的长度 传入参数 "Content-Length"字符串,表示获取文件内容长度。
*/
void GetResponseHeader()
{
StartCoroutine(SendRequest_GetResponseHeader());
}
IEnumerator SendRequest_GetResponseHeader()
{
UnityWebRequest
webRequest = UnityWebRequest.Head(
"http://www.chinar.xin/chinarweb/WebRequest/Get/00-效果.mp4"); //创建UnityWebRequest对象
yield return webRequest.SendWebRequest(); //等待返回请求的信息
if (webRequest.result == UnityWebRequest.Result.ProtocolError ||
webRequest.result == UnityWebRequest.Result.ConnectionError) //如果其 请求失败,或是 网络错误
{
Debug.Log(webRequest.error); //打印错误原因
}
else //请求成功
{
long totalLength = long.Parse(webRequest.GetResponseHeader("Content-Length")); //首先拿到文件的全部长度
Debug.Log("totalLength"); //打印文件长度
}
}
#endregion
/*
* -------------------------------------------常用属性-------------------------------------------
* 属性 类型 含义
* timeout int 等待时间(秒)超过此数值是 UnityWebReqest的尝试连接将终止
* UnityWebRequest.Result.ProtocolError bool HTTP响应出现出现错误
* UnityWebRequest.Result.ConnectionError bool 系统出现错误
* error string 描述 UnityWebRequest对象在处理HTTP请求或响应时遇到的任何系统错误
* downloadProgress float 表示从服务器下载数据的进度
* uploadProgress float 表示从服务器上传数据的进度
* isDone bool 是否完成与远程服务器的通信
*/
#region DownloadFill
public Slider ProgressBar; //进度条
public Text SliderValue; //滑动条值
public Button startBtn; //开始按钮
void DownLoadFile()
{
//初始化进度条和文本框
ProgressBar.value = 0;
SliderValue.text = "0.0%";
startBtn.onClick.AddListener(OnClickStartDownload);
}
/// <summary>
/// 回调函数:开始下载
/// </summary>
public void OnClickStartDownload()
{
StartCoroutine(DownloadFile());
}
/// <summary>
/// 协程:下载文件
/// </summary>
IEnumerator DownloadFile()
{
UnityWebRequest uwr =
UnityWebRequest.Get(
"file:///C:/Users/Administrator/Music/VipSongsDownload/全昭弥 (전소미) - What You Waiting For.mflac"); //创建UnityWebRequest对象,将Url传入
uwr.SendWebRequest(); //开始请求
if (uwr.isNetworkError || uwr.isHttpError) //如果出错
{
Debug.Log(uwr.error); //输出 错误信息
}
else
{
while (!uwr.isDone) //只要下载没有完成,一直执行此循环
{
ProgressBar.value = uwr.downloadProgress; //展示下载进度
SliderValue.text = Math.Floor(uwr.downloadProgress * 100) + "%";
yield return 0;
}
if (uwr.isDone) //如果下载完成了
{
print("完成");
ProgressBar.value = 1; //改变Slider的值
SliderValue.text = 100 + "%";
}
byte[] results = uwr.downloadHandler.data;
// 注意真机上要用Application.persistentDataPath
CreateFile(Application.streamingAssetsPath + "/MP4/test.mp4", results,
uwr.downloadHandler.data.Length); //事先要在StreamingAssets创建一个MP4文件夹
AssetDatabase.Refresh(); //Asset资源刷新
}
}
/// <summary>
/// 这是一个创建文件的方法
/// </summary>
/// <param name="path">保存文件的路径</param>
/// <param name="bytes">文件的字节数组</param>
/// <param name="length">数据长度</param>
void CreateFile(string path, byte[] bytes, int length)
{
Stream swream;
FileInfo file = new FileInfo(path);
if (!file.Exists)
{
swream = file.Create();
}
else
{
return;
}
swream.Write(bytes, 0, length);
swream.Close();
swream.Dispose();
}
#endregion
#region BreakpointDownload 断点续传
private bool _isStop; //是否暂停
public Slider _ProgressBar; //进度条
public Text _SliderValue; //滑动条值
public Button _startBtn; //开始按钮
public Button pauseBtn; //暂停按钮
private string Url = "file:///C:/Users/Administrator/Music/VipSongsDownload/全昭弥 (전소미) - What You Waiting For.mflac";
void BreakpointDownload()
{
//初始化进度条和文本框
_ProgressBar.value = 0;
_SliderValue.text = "0.0%";
startBtn.onClick.AddListener(SatrtDownload);
pauseBtn.onClick.AddListener(OnClickStop);
}
/// <summary>
/// 回调函数:开始下载
/// </summary>
public void SatrtDownload()
{
// 注意真机上要用Application.persistentDataPath
StartCoroutine(DownloadFile(Url, Application.streamingAssetsPath + "/MP4/test.mp4", CallBack));
}
/// <summary>
/// 协程:下载文件
/// </summary>
/// <param name="url">请求的Web地址</param>
/// <param name="filePath">文件保存路径</param>
/// <param name="callBack">下载完成的回调函数</param>
/// <returns></returns>
IEnumerator DownloadFile(string url, string filePath, Action callBack)
{
UnityWebRequest huwr = UnityWebRequest.Head(url); //Head方法可以获取到文件的全部长度
yield return huwr.SendWebRequest();
if (huwr.isNetworkError || huwr.isHttpError) //如果出错
{
Debug.Log(huwr.error); //输出 错误信息
}
else
{
long totalLength = long.Parse(huwr.GetResponseHeader("Content-Length")); //首先拿到文件的全部长度
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; //当前文件长度
Debug.Log(fs.Length);
if (nowFileLength < totalLength)
{
Debug.Log("还没下载完成");
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) //只要下载没有完成,一直执行此循环
{
if (_isStop) 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;
ProgressBar.value = (float) nowFileLength / totalLength;
SliderValue.text = Math.Floor((float) nowFileLength / totalLength * 100) + "%";
if (nowFileLength >= totalLength) //如果下载完成了
{
ProgressBar.value = 1; //改变Slider的值
SliderValue.text = 100 + "%";
callBack?.Invoke();
break;
}
}
}
}
}
}
}
}
/// <summary>
/// 下载完成后的回调函数
/// </summary>
void CallBack()
{
Debug.Log("下载完成");
}
/// <summary>
/// 暂停下载
/// </summary>
public void OnClickStop()
{
if (_isStop)
{
pauseBtn.GetComponentInChildren<Text>().text = "暂停下载";
Debug.Log("继续下载");
_isStop = !_isStop;
OnClickStartDownload();
}
else
{
pauseBtn.GetComponentInChildren<Text>().text = "继续下载";
Debug.Log("暂停下载");
_isStop = !_isStop;
}
}
#endregion
}
参考了 林新发 的文章,把内容都写入代码中方便查看和加深印象。