需求:当前需求是 需要客户端更新 ab 包的时候可以断点续传
原理:原理就是请求特定的 字节区域,比如:下载一个文件,第一次请求区域为0-10M的字节,第二次为10M-20M,这个区域跨度自己设置就行。当你第三次没下载完关闭app,再次下载的时候,只需要读取你没下载完成的文件(边下载变存本地的文件)字节长度,从这个长度开始请求下载就可以了
使用:用的是http协议下载,HTTP 方面,Apache 或 Ngnix 默认都是支持 Accept-Ranges 的,别的服务器需要你自己去处理。
核心代码:
string _url = "";
Dictionary<string, string> httpHead = new Dictionary<string, string>();
httpHead.Add("Range", "bytes=" + 请求其实位置+ "-" + 请求结束位置);
WWW m_iWWW = new WWW(_url, null, httpHead);
实例:
void Start() {
StartCoroutine(RunWithContinue());
}
private WWW m_iWWW = null;
private const int CHUNK_SIZE = 10 * 1024 * 1024; //断点续传时,每次请求10M
private long m_nChunk = 0; //在分段下载中,记录当前下载段的长度
private long m_nContinueDownloaded = 0; //在分段下载中,记录当前下载文件已下载长度
private IEnumerator RunWithContinue()
{
int nStartPos = 0;
long nFileTotalLength = 102627178;
System.IO.FileStream fsTmpFile = System.IO.File.Create(@"E:\UnitySpace\Test\Assets\abc.zip");
while (nFileTotalLength > nStartPos)
{
string _url = "";
Dictionary<string, string> httpHead = new Dictionary<string, string>();
httpHead.Add("Range", "bytes=" + nStartPos.ToString() + "-" + (nStartPos + CHUNK_SIZE).ToString());
m_iWWW = new WWW(_url, null, httpHead);
yield return StartCoroutine(WaitForWWWWithTimeOut(m_iWWW, 10)); // 替换成带超时的版本 [3/11/2014 yao]
if (!m_iWWW.isDone || (m_iWWW.error != null && m_iWWW.error.Length > 0))
{
Debug.Log("nStartPos:" + nStartPos + " CHUNK_SIZE:" + CHUNK_SIZE + " total:" + (nStartPos + CHUNK_SIZE));
Debug.LogError("error======" + m_iWWW.error);
}
try
{
fsTmpFile.Write(m_iWWW.bytes, 0, m_iWWW.bytes.Length);
}
catch (System.Exception ex)
{
Debug.LogError("Exception======");
break;
}
nStartPos += m_iWWW.bytes.Length;
m_nContinueDownloaded = nStartPos;
m_iWWW.Dispose();
m_iWWW = null;
}
fsTmpFile.Close();
fsTmpFile = null;
Debug.LogError("结束");
}
private IEnumerator WaitForWWWWithTimeOut(WWW iWWW, float fTimeOut)
{
float fWait = 0;
float fProgress = 0;
do
{
//判断是否完成并等待
if (iWWW.isDone)
{
yield break;
}
yield return new WaitForSeconds(0.1f);
//累计超时时间
fWait += 0.1f;
if (fWait > fTimeOut)
{
yield break;
}
//如果进度走动了,则重新判断超时时间
if (m_iWWW.progress > fProgress)
{
fProgress = m_iWWW.progress;
fWait = 0;
}
} while (true);
}