Unity (BestHTTP)資料請求及檔案下載下傳
Unity工程中關于HTTP的使用非常常見,Unity本身內建的WWW便可以進行網絡請求處理,但是,WWW本身卻有很多的局限性,而BestHttp插件卻把HTTP這一塊處理的很好,今天學習了一下,并做個簡單的筆記,寫一個小Demo
建立APIRequestTest對象來管理程式執行過程中關于HTTP的資料請求及下載下傳 這個腳本中有請求完成回調,下載下傳進度回調及下載下傳資源完成回調,基本能滿足正常使用,代碼注釋很清晰
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using BestHTTP;
using UnityEngine;
public class APIRequestTest
{
public delegate void HTTPRequestCallBack(APIRequestTest apiRequest,bool isSuccess,string responseText);
public delegate void HTTPDownProgressCallBack(APIRequestTest apiRequest,float progress);
public delegate void HTTPDownCompleteCallBack(APIRequestTest apiRequest,bool isSuccess,int code,string savePath);
private HTTPRequestCallBack requestCallBack;//請求完成回調
private HTTPDownProgressCallBack downProgressCallBack;//下載下傳進度回調
private HTTPDownCompleteCallBack downCompleteCallBack;//下載下傳完成回調
//正式伺服器根路徑
private static string baseUrl = "";
//測試伺服器根路徑
private static string testBaseUrl = "http://192.168.2.129:55555/v1/";
//是否用測試伺服器
public static bool useTestServer = true;
private HTTPRequest request;
private TimeSpan requestTimeOut = TimeSpan.FromSeconds(30);//請求逾時時間設定 30S
private string downSavePath;//下載下傳資源的本地儲存路徑
private int downFileCount = -1;//需要下載下傳資源的長度
private int downedFileCount = 0;//已經下載下傳資源的長度
private float downProgressValue = 0;//下載下傳資源的進度
private APIRequestTest(string _baseUrl=null) {
if (!string.IsNullOrEmpty(_baseUrl))
{
baseUrl = _baseUrl;
}
}
//建立請求對象
public static APIRequestTest Create(string _baseUrl=null) {
if (useTestServer)
{
_baseUrl = testBaseUrl;
}
return new APIRequestTest(_baseUrl);
}
//設定請求逾時時間
public APIRequestTest SetTimeOut(double seconds) {
if (seconds<=0)
{
return this;
}
requestTimeOut = TimeSpan.FromSeconds(seconds);
return this;
}
//設定請求優先級 優先級較高的請求将比優先級較低的請求更快地從請求隊列中選擇。
public APIRequestTest SetPriority(int priority) {
if (request!=null)
{
request.Priority = priority;
}
return this;
}
#region 資料請求
//發送請求
public APIRequestTest Send(HTTPMethods method,string url,Dictionary<string,string> paramsDict, HTTPRequestCallBack sendCallBack =null) {
requestCallBack = sendCallBack;
if (Application.internetReachability==NetworkReachability.NotReachable)//沒有網絡連接配接
{
Debug.LogError("【 檢查裝置是否可以通路網絡!!! 】");
requestCallBack?.Invoke(this,false,"裝置無法進行網絡連接配接");
return this;
}
if (method ==HTTPMethods.Get)
{
SendGetMethod(url,paramsDict);
}
else if (method==HTTPMethods.Post)
{
SendPostMethod(url,paramsDict);
}
if (request==null)
{
Debug.LogError("【 建立HTTPRequest失敗!!! 】");
requestCallBack?.Invoke(this, false, "建立HTTPRequest失敗");
return this;
}
SetRequestHeaders(request);
//禁止緩存
request.DisableCache = true;
//設定逾時時間
request.Timeout = requestTimeOut;
//發送請求
request.Send();
return this;
}
//終止請求
public APIRequestTest Abort() {
if (request!=null)
{
request.Abort();
}
return this;
}
//設定請求頭
public void SetRequestHeaders(HTTPRequest _request) {
//_request.SetHeader("name","value");
}
//Get方式請求資料
void SendGetMethod(string url,Dictionary<string,string> paramsDict) {
string requestUrl = baseUrl + url+"?";
if (paramsDict!=null&¶msDict.Count>0)
{
int id = 0;
foreach (var item in paramsDict.Keys)
{
string key = item;
string value = paramsDict[key];
if (id < paramsDict.Count - 1)
{
requestUrl += key + "=" + value + "&";
}
else {
requestUrl += key + "=" + value;
}
id++;
}
}
Uri uri = new Uri(requestUrl);
request = new HTTPRequest(uri,HTTPMethods.Get, OnRequestFinished);
}
//Post方式請求資料
void SendPostMethod(string url,Dictionary<string, string> paramsDict) {
string requestUrl = baseUrl + url;
Uri uri = new Uri(requestUrl);
request = new HTTPRequest(uri,HTTPMethods.Post,OnRequestFinished);
if (paramsDict!=null&¶msDict.Count>0)
{
foreach (var item in paramsDict.Keys)
{
string key = item;
string value = paramsDict[key];
request.AddField(key,value);
}
}
}
//資料請求完成回調
void OnRequestFinished(HTTPRequest _request, HTTPResponse response) {
int responseCode = 0;//請求傳回碼
bool isSuccess = false;
string responseText = null;
if (_request.State == HTTPRequestStates.Finished)//請求完成
{
responseCode = response.StatusCode;
isSuccess = response.IsSuccess;
responseText = response.DataAsText;
}
else if (_request.State == HTTPRequestStates.TimedOut || _request.State == HTTPRequestStates.ConnectionTimedOut)//請求或連接配接逾時
{
responseText = "請求逾時";
}
else if (_request.State == HTTPRequestStates.Error)//請求報錯
{
if (request.Exception != null)
{
responseText = request.Exception.Message;
if (string.IsNullOrEmpty(responseText))
{
responseText = "請求報錯";
}
}
else
{
responseText = "請求報錯";
}
}
else {//其他異常
responseText = _request.State.ToString();
}
#if UNITY_EDITOR //編輯器模式下列印請求資料
string debugStr = "【HTTPRequest State="+ _request.State.ToString()+" isSuccess="+isSuccess+"】:";
string url = _request.Uri.AbsoluteUri+"\n";
debugStr = "<color=blue>"+debugStr + url+"</color>" + System.Text.RegularExpressions.Regex.Unescape(responseText);
Debug.Log(debugStr);
#endif
requestCallBack?.Invoke(this,isSuccess,responseText);
}
#endregion
#region 資源下載下傳
/// <summary>
/// 下載下傳檔案
/// </summary>
/// <param name="url">資源url</param>
/// <param name="savePath">儲存本地的路徑</param>
/// <param name="progressCallBack">下載下傳進度回調</param>
/// <param name="completeCallBack">下載下傳完成回調</param>
/// <param name="forceDown">是否強制下載下傳(是否替換本地檔案)</param>
public void DownFile(string url, string savePath, HTTPDownProgressCallBack progressCallBack, HTTPDownCompleteCallBack completeCallBack, bool forceDown = false) {
downCompleteCallBack = completeCallBack;
downProgressCallBack = progressCallBack;
downSavePath = savePath;
downFileCount = -1;
downedFileCount = 0;
if (string.IsNullOrEmpty(url)||string.IsNullOrEmpty(savePath))
{
Debug.LogError("【 非法的下載下傳位址或存儲位址! 】");
downCompleteCallBack?.Invoke(this,false,300,savePath);
return;
}
if (!forceDown)//非強制下載下傳
{
if (File.Exists(savePath))//本地存在目标檔案
{
if (savePath.EndsWith(".tmp", StringComparison.CurrentCulture))
{//删除本地臨時檔案
File.Delete(savePath);
Debug.Log("删除檔案:"+savePath);
}
else {
Debug.Log("重複資源,無需下載下傳:"+savePath);
downProgressCallBack?.Invoke(this,1);
downCompleteCallBack?.Invoke(this, true, 200, savePath);
return;
}
}
else {//新資源
Debug.Log("新資源:"+savePath);
}
}
Uri uri = new Uri(url);
request = new HTTPRequest(uri,DownRequestFinished);
request.UseStreaming = true;
request.StreamFragmentSize = 1024 * 512;
request.DisableCache = true;
request.Timeout = requestTimeOut;
request.ConnectTimeout =requestTimeOut;
request.Send();
}
//下載下傳資源請求結束回調
private void DownRequestFinished(HTTPRequest _request, HTTPResponse response) {
HTTPRequestStates states = _request.State;
if (states==HTTPRequestStates.Processing)//資料請求中
{
if (downFileCount == -1)
{
string value = response.GetFirstHeaderValue("content-length");
if (!string.IsNullOrEmpty(value))
{
downFileCount= int.Parse(value);
Debug.Log("GetFirstHeaderValue content-length = " + downFileCount);
}
}
List<byte[]> bytes;
bytes = response.GetStreamedFragments();
SaveFile(bytes);
downProgressValue = downedFileCount / (float)downFileCount;
downProgressCallBack?.Invoke(this,downProgressValue);
}
else
if (states == HTTPRequestStates.Finished)//資料請求完成
{
if (response.IsSuccess)
{
List<byte[]> bytes;
bytes = response.GetStreamedFragments();
SaveFile(bytes);
if (response.IsStreamingFinished)
{
downProgressCallBack?.Invoke(this, 1);
downCompleteCallBack?.Invoke(this,true,response.StatusCode,downSavePath);
}
else {
Debug.LogError("【HTTPRequestStates.Finished成功,Response.IsStreamingFinished失敗】");
downCompleteCallBack?.Invoke(this, false, response.StatusCode, downSavePath);
}
}
else {
downCompleteCallBack?.Invoke(this, false, response.StatusCode, downSavePath);
string logMsg = string.Format("{0} - {1} - {2}", response.StatusCode, response.Message, _request.Uri.AbsoluteUri);
Debug.LogError(logMsg);
}
}
else {//資料請求失敗
Debug.LogError("DownFile失敗:"+_request.State.ToString());
downCompleteCallBack?.Invoke(this,false,-1, downSavePath);
}
}
//儲存資源到本地
private void SaveFile(List<byte[]> bytes) {
if (bytes==null||bytes.Count<=0)
{
return;
}
using (FileStream fs = new FileStream(downSavePath,FileMode.Append)) {
for (int i = 0; i < bytes.Count; i++)
{
byte[] byteArr = bytes[i];
fs.Write(byteArr,0,byteArr.Length);
downedFileCount+=byteArr.Length;
}
}
}
#endregion
}
使用
請求資料
string url = "student/report_card";
Dictionary<string, string> info = new Dictionary<string, string>();
info["lesson_id"] = "1287";
APIRequestTest.Create().Send(BestHTTP.HTTPMethods.Get, url, a, (APIRequestTest api, bool isSuccess, string responseText) =>{
if (isSuccess)
{
Debug.LogError("請求成功");
}
else
{
Debug.LogError("請求失敗");
}
Debug.LogError(responseText);
});
資源下載下傳
string downUrl = "資源網絡路徑";
string savePath = Application.streamingAssetsPath + "/testVideo.mp4";
APIRequestTest.Create().DownFile(downUrl, savePath, (APIRequestTest apiRequest, float value) =>
{
Debug.LogError(value.ToString("f2"));
}, (APIRequestTest api, bool isSuccess, int code, string path) =>
{
if (isSuccess)
{
Debug.LogError("下載下傳成功");
}
else
{
Debug.LogError("下載下傳失敗");
}
Debug.LogError(path);
});