一.使用 Http 显示断点下载
using System;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using UnityEngine;
public class BreakpointDownloader
{
public static void download(string downUrl, string writeFilePath, Action<string> errAction, Action<double, bool> callBack)
{
long startPos = 0;
FileStream fs = null;
if (File.Exists(writeFilePath))
{
fs = new FileStream(writeFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
startPos = fs.Length;
fs.Seek(startPos, SeekOrigin.Current);
}
else
{
string direName = Path.GetDirectoryName(writeFilePath);
if (!Directory.Exists(direName))
Directory.CreateDirectory(direName);
fs = new FileStream(writeFilePath, FileMode.Create);
}
HttpWebRequest request = null;
WebResponse respone = null;
Stream ns = null;
try
{
ServicePointManager.ServerCertificateValidationCallback = MyRemoteCertificateValidationCallback;
request = WebRequest.Create(downUrl) as HttpWebRequest;
request.ReadWriteTimeout = 10000;
request.Timeout = 10000;
if (startPos > 0)
request.AddRange((int)startPos);
respone = request.GetResponse();
ns = respone.GetResponseStream();
long totalSize = respone.ContentLength + startPos;
long curSize = startPos;
LogDown(curSize, totalSize, "已下");
if (curSize == totalSize)
{
if (callBack != null)
callBack(1, true);
}
else
{
int oneReadLen = 1024 * 8;
byte[] bytes = new byte[oneReadLen];
int readSize = ns.Read(bytes, 0, oneReadLen);
while (readSize > 0)
{
fs.Write(bytes, 0, readSize);
curSize += readSize;
readSize = ns.Read(bytes, 0, oneReadLen);
if (callBack != null)
callBack((double)curSize / totalSize, false);
}
if (curSize == totalSize)
{
LogDown(curSize - startPos, totalSize, "又");
if (callBack != null)
callBack(1, true);
}
else
{
if (errAction != null)
{
string err = "下载出错,文件大小不对,请重启后重试!";
Debug.LogError(err);
errAction(err);
}
}
}
}
catch (WebException ex)
{
if (errAction != null)
{
string err = "下载出错:" + ex.Message + ",请重启后重试!";
Debug.LogError(err);
errAction(err);
}
}
finally
{
if (fs != null)
{
fs.Flush();
fs.Close();
fs = null;
}
if (ns != null)
ns.Close();
if (respone != null)
respone.Close();
if (request != null)
request.Abort();
}
}
private static void LogDown(double fileLen, long totalLength, string headStr)
{
double precess = fileLen / totalLength;
precess = GetPreciseDecimal(precess, 4);
precess *= 100;
StringBuilder sb = new StringBuilder();
sb.Append(headStr);
sb.Append("载文件长度:");
sb.Append(precess);
sb.Append("% nowFileLength:");
sb.Append(fileLen);
sb.Append(" totalLength:");
sb.Append(totalLength);
Debug.Log(sb.ToString());
}
public static double GetPreciseDecimal(double nNum, int n)
{
float nDecimal = Mathf.Pow(10, n);
int i = (int)(nNum * nDecimal);
nNum = i / nDecimal;
return nNum;
}
private static bool MyRemoteCertificateValidationCallback(System.Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
bool isOk = true;
if (sslPolicyErrors != SslPolicyErrors.None)
{
for (int i = 0; i < chain.ChainStatus.Length; i++)
{
if (chain.ChainStatus[i].Status == X509ChainStatusFlags.RevocationStatusUnknown)
continue;
chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain;
chain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 1, 0);
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllFlags;
bool chainIsValid = chain.Build((X509Certificate2)certificate);
if (!chainIsValid)
{
isOk = false;
break;
}
}
}
return isOk;
}
}
二.单开线程 控制下载 显示下载进度
using System.Threading;
using UnityEngine;
using UnityEngine.UI;
public class HttpWebRequestStart : MonoBehaviour
{
private string downUrl = "1.apk";
private string writePath = "";
public Slider slider;
public Text text;
public Button startDown;
private float downProcess=0;
private bool isDownOver = false;
private Thread thread = null;
private double lastProcess;
void Start()
{
writePath = Application.streamingAssetsPath + "/Http-Download/1.apk";
startDown.onClick.AddListener(StartDownClick);
}
private void StartDownClick()
{
thread = new Thread(() =>
{
BreakpointDownloader.download(downUrl, writePath, DownErrAcTion, UpdateDownProcessData);
});
thread.Start();
thread.IsBackground = true;
}
private void DownErrAcTion(string err)
{
Debug.LogError("下载错误:" + err);
}
private void UpdateDownProcessData(double procee,bool isOver)
{
downProcess = (float)procee;
isDownOver = isOver;
if (isOver)
Debug.LogWarning("http下载结束");
}
void Update()
{
UpdateProcess();
}
private void UpdateProcess()
{
if (slider == null)
return;
if (isDownOver && slider.value == 1)
return;
if(slider.value== downProcess)
return;
slider.value = downProcess;
double newProcess = BreakpointDownloader.GetPreciseDecimal(downProcess,3) * 100;
if (lastProcess != newProcess)
{
text.text = string.Format("下载进度:{0}{1}", lastProcess, "%");
lastProcess = newProcess;
}
}
private void OnDestroy()
{
if (thread != null)
thread.Abort();
}
}