上篇文章介绍了Http请求的接口封装,本篇具体介绍基于HttpWebRequest接口实现的资源请求下载。HttpWebRequestHelper实现完全重新请求下载和断点续传,并且是异步多线程执行的。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net;
using System.IO;
using System.Text;
using System;
using System.Threading;
/*
* Author:W
* .NET的网络请求下载接口
*/
namespace W.GameFramework.HotUpdate
{
public class HttpWebRequestHelper : HttpHelper
{
private HttpWebRequest httpWebRequest = null;
private HttpWebResponse httpWebResponse = null;
private Thread requestThread = null;
private FileStream fileStream = null;
private Stream responseStream = null;
public override void SendHttpRequest(string url, string path, DownloadType downloadType = DownloadType.New, OnDownloadBeginHandler onDownloadBeginHandler = null, OnDownloadEndHandler onDownloadEndHandler = null,
OnDownloadProgressHanlder onDownloadProgressHanlder = null, OnDownloadErrorHandler onDownloadErrorHandler = null)
{
base.SendHttpRequest(url, path,downloadType, onDownloadBeginHandler, onDownloadEndHandler,onDownloadProgressHanlder, onDownloadErrorHandler);
if (downloadType == DownloadType.New)
{
SendHttpRequestByNew();
}
else if (downloadType == DownloadType.Continue)
{
SendHttpRequestByContinue();
}
}
#region 异步请求下载【完整重新下载】
/// <summary>
/// 请求下载:完整重新下载
/// </summary>
private void SendHttpRequestByNew()
{
try
{
httpWebRequest = WebRequest.Create(url) as HttpWebRequest;
httpWebRequest.Timeout = timeOut;
httpWebRequest.Method = method;
AsyncCallback asyncCallback = new AsyncCallback(OnResponseCallBack);
httpWebRequest.BeginGetResponse(asyncCallback, null);
//文件请求下载开始回调
if (OnDownloadBeginHandler != null)
OnDownloadBeginHandler();
}
catch (Exception e)
{
//文件请求下载错误回调
if (OnDownloadErrorHandler != null)
OnDownloadErrorHandler(e.Message);
if (httpWebRequest != null)
httpWebRequest.Abort();
}
}
/// <summary>
/// 异步请求返回结果处理
/// </summary>
/// <param name="asyncResult"></param>
private void OnResponseCallBack(IAsyncResult asyncResult)
{
try
{
httpWebResponse = httpWebRequest.EndGetResponse(asyncResult) as HttpWebResponse;
//计算请求加载的文件总长度
fileLength = httpWebResponse.ContentLength;
if (httpWebResponse.StatusCode == HttpStatusCode.OK)
{
//检查本地是否缓存请求下载文件,如果有则删除
if (File.Exists(path))
File.Delete(path);
fileStream = new FileStream(path, FileMode.Create, FileAccess.Write);
//计算文件本地已加载的长度
fileCurLength = fileStream.Length;
progress = (float)fileCurLength / fileLength;
//请求内容Byte数据读取
responseStream = httpWebResponse.GetResponseStream();
byte[] readBuff = new byte[2048];
int len = -1;
while ((len = responseStream.Read(readBuff, 0, readBuff.Length)) > 0)
{
//停止请求下载
if (IsStop)
{
Clear();
return;
}
fileStream.Write(readBuff, 0, len);
fileCurLength += len;
progress = (float)fileCurLength / fileLength;
}
//文件请求下载完成回调
if (OnDownloadEndHandler != null)
OnDownloadEndHandler();
}
else
{
//文件请求下载错误回调
if (OnDownloadErrorHandler != null)
OnDownloadErrorHandler(httpWebResponse.StatusDescription);
}
}
catch (Exception e)
{
//文件请求下载错误回调
if (OnDownloadErrorHandler != null)
OnDownloadErrorHandler(e.Message);
}
finally
{
Clear();
}
}
#endregion
#region 开线程请求下载【断点续传下载】
/// <summary>
/// 请求下载 【断点续传下载时】
/// </summary>
private void SendHttpRequestByContinue()
{
requestThread = new Thread(AsyncSendHttpRequest);
requestThread.IsBackground = false;
requestThread.Start();
}
/// <summary>
/// 多线程异步请求下载
/// </summary>
private void AsyncSendHttpRequest()
{
try
{
fileStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write);
//计算请求下载文件本地已缓存的数据大小
fileCurLength = fileStream.Length;
//先发出请求,获取请求下载的文件大小信息
httpWebRequest = WebRequest.Create(url) as HttpWebRequest;
httpWebRequest.Method = "HEAD";
httpWebRequest.Timeout = timeOut;
httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse;
if (httpWebResponse.StatusCode == HttpStatusCode.OK)
{
//计算请求下载文件总的大小
fileLength = httpWebResponse.ContentLength;
progress = (float)fileCurLength / fileLength;
if (OnDownloadBeginHandler != null)
OnDownloadBeginHandler();
//说明请求下载文件未完成下载,请继续接着下载
if (progress < 1f)
{
//设定文件写入流的开始写入位置
fileStream.Seek(fileCurLength, SeekOrigin.Begin);
httpWebRequest = WebRequest.Create(url) as HttpWebRequest;
httpWebRequest.Method = method;
httpWebRequest.Timeout = timeOut;
//向请求声明下载文件下载开始位置
httpWebRequest.AddRange((int)fileCurLength);
//请求返回
httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse;
if (httpWebResponse.StatusCode == HttpStatusCode.OK
|| httpWebResponse.StatusCode == HttpStatusCode.PartialContent)
{
responseStream = httpWebResponse.GetResponseStream();
byte[] readBuff = new byte[2048];
int len = -1;
while ((len = responseStream.Read(readBuff, 0, readBuff.Length)) > 0)
{
//停止请求下载
if (IsStop)
{
Clear();
return;
}
fileStream.Write(readBuff, 0, len);
fileCurLength += len;
progress = (float)fileCurLength / fileLength;
}
if (OnDownloadEndHandler != null)
OnDownloadEndHandler();
}
else
{
if (OnDownloadErrorHandler != null)
OnDownloadErrorHandler(httpWebResponse.StatusDescription);
}
}
else
{
progress = 1f;
if (OnDownloadEndHandler != null)
OnDownloadEndHandler();
}
}
else
{
if (OnDownloadErrorHandler != null)
OnDownloadErrorHandler(httpWebResponse.StatusDescription);
}
}
catch (Exception e)
{
if (OnDownloadErrorHandler != null)
OnDownloadErrorHandler(e.Message);
}
finally
{
Clear();
}
}
#endregion
public override void Clear()
{
if (responseStream != null)
{
responseStream.Close();
responseStream = null;
}
if (httpWebResponse != null)
{
httpWebResponse.Close();
httpWebResponse = null;
}
if (httpWebRequest != null)
{
httpWebRequest.Abort();
httpWebRequest = null;
}
if (fileStream != null)
{
fileStream.Flush();
fileStream.Close();
fileStream = null;
}
if (requestThread != null)
{
requestThread.Abort();
requestThread = null;
}
}
}
}
下篇文章链接https://blog.youkuaiyun.com/wlqchengzhangji/article/details/118704731