基类

首先先创建一个基类,里面存放下载需要的一些数据,例如文件url,下载存放路径等等。

public abstract class DownloadItem {/// <summary>/// 网络资源url路径/// </summary>protected string m_srcUrl;/// <summary>/// 资源下载存放路径,不包含文件名/// </summary>protected string m_savePath;/// <summary>/// 文件名,不包含后缀/// </summary>protected string m_fileNameWithoutExt;/// <summary>/// 文件后缀/// </summary>protected string m_fileExt;/// <summary>/// 下载文件全路径,路径+文件名+后缀/// </summary>protected string m_saveFilePath;/// <summary>/// 原文件大小/// </summary>protected long m_fileLength;/// <summary>/// 当前下载好了的大小/// </summary>protected long m_currentLength;/// <summary>/// 是否开始下载/// </summary>protected bool m_isStartDownload;public bool isStartDownload {get {return m_isStartDownload;}}public DownloadItem(string url, string path) {m_srcUrl = url;m_savePath = path;m_isStartDownload = false;m_fileNameWithoutExt = Path.GetFileNameWithoutExtension(m_srcUrl);m_fileExt = Path.GetExtension(m_srcUrl);m_saveFilePath = string.Format("{0}/{1}{2}", m_savePath, m_fileNameWithoutExt, m_fileExt);}/// <summary>/// 开始下载/// </summary>/// <param name="callback">下载完成回调</param>public virtual void StartDownload(Action callback = null) {if(string.IsNullOrEmpty(m_srcUrl) || string.IsNullOrEmpty(m_savePath)) {return;}//若存放目录不存在则创建目录FileTool.CreateDirectory(m_saveFilePath);}/// <summary>/// 获取下载进度/// </summary>/// <returns>进度,0-1</returns>public abstract float GetProcess();/// <summary>/// 获取当前下载了的文件大小/// </summary>/// <returns>当前文件大小</returns>public abstract long GetCurrentLength();/// <summary>/// 获取要下载的文件大小/// </summary>/// <returns>文件大小</returns>public abstract long GetLength();public abstract void Destroy();
}

HTTP

这种方式下载,我们采用的是边读取边生成对应文件,适合较大文件下载。关于断点续传的处理,我们下载的时候,先根据读取的内容生成一个临时文件,当全部下载好后,才将这个临时文件转换成正式的文件名。若中途下载中断,已下载好的那部分文件依据在对应目录下,我们下次下载可以直接在上次下载的临时文件后添加内容。

所以下载逻辑就是,每次下载先判断是否有对应的临时文件,若没有则是第一次下载,从初始位置读取下载,若有该文件,则读取该文件信息,获取文件大小当之后的读取下载的偏移量,从当前位置开始下载,直至下载完成。

/// <summary>
/// HTTP的方式下载,支持断点续传
/// </summary>
public class HttpDownloadItem : DownloadItem {/// <summary>/// 临时文件后缀名/// </summary>string m_tempFileExt = ".temp";/// <summary>/// 临时文件全路径/// </summary>string m_tempSaveFilePath;public HttpDownloadItem(string url, string path) : base(url, path) {m_tempSaveFilePath = string.Format("{0}/{1}{2}", m_savePath, m_fileNameWithoutExt, m_tempFileExt);}public override void StartDownload(Action callback = null) {base.StartDownload();UICoroutine.uiCoroutine.StartCoroutine(Download(callback));}IEnumerator Download(Action callback = null) {HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_srcUrl);request.Method = "GET";FileStream fileStream;if(File.Exists(m_tempSaveFilePath)) {//若之前已下载了一部分,继续下载fileStream = File.OpenWrite(m_tempSaveFilePath);m_currentLength = fileStream.Length;fileStream.Seek(m_currentLength, SeekOrigin.Current);//设置下载的文件读取的起始位置request.AddRange((int)m_currentLength);} else {//第一次下载fileStream = new FileStream(m_tempSaveFilePath, FileMode.Create, FileAccess.Write);m_currentLength = 0;}HttpWebResponse response = (HttpWebResponse)request.GetResponse();Stream stream = response.GetResponseStream();//总的文件大小=当前需要下载的+已下载的m_fileLength = response.ContentLength + m_currentLength;m_isStartDownload = true;int lengthOnce;int bufferMaxLength = 1024 * 20;while(m_currentLength < m_fileLength) {byte[] buffer = new byte[bufferMaxLength];if(stream.CanRead) {//读写操作lengthOnce = stream.Read(buffer, 0, buffer.Length);m_currentLength += lengthOnce;fileStream.Write(buffer, 0, lengthOnce);} else {break;}yield return null;}m_isStartDownload = false;response.Close();stream.Close();fileStream.Close();//临时文件转为最终的下载文件File.Move(m_tempSaveFilePath, m_saveFilePath);if(callback != null) {callback();}}public override float GetProcess() {if(m_fileLength > 0) {return Mathf.Clamp((float)m_currentLength / m_fileLength, 0, 1);}return 0;}public override long GetCurrentLength() {return m_currentLength;}public override long GetLength() {return m_fileLength;}public override void Destroy() {}
}

补充

上述代码用到了两个自定义的方法FileTool.CreateDirectory()和FileTool.CreatFile(),内容很简单,如下

public class FileTool {/// <summary>/// 创建目录/// </summary>/// <param name="filePath">需要创建的目录路径</param>public static void CreateDirectory(string filePath) {if(!string.IsNullOrEmpty(filePath)) {string dirName = Path.GetDirectoryName(filePath);if(!Directory.Exists(dirName)) {Directory.CreateDirectory(dirName);}}}/// <summary>/// 创建文件/// </summary>/// <param name="filePath">文件路径</param>/// <param name="bytes">文件内容</param>public static void CreatFile(string filePath, byte[] bytes) {FileInfo file = new FileInfo(filePath);Stream stream = file.Create();stream.Write(bytes, 0, bytes.Length);stream.Close();stream.Dispose();}
}

UICoroutine相关的代码,深表歉意。UICoroutine在这个例子中的作用其实就是场景中新建一个GameObject,专门用来启用协程,因为前面的几个类没有继承于MonoBehaviour,所以无法直接调用StartCoroutine方法

public class UICoroutine : MonoBehaviour {private static UICoroutine mInstance = null;public static UICoroutine uiCoroutine {get {if(mInstance == null) {GameObject go = new GameObject();if(go != null) {go.name = "_UICoroutine";go.AddComponent<UICoroutine>();} else {Debug.LogError("Init UICoroutine faild. GameObjet can not be null.");}}return mInstance;}}void Awake() {DontDestroyOnLoad(gameObject);mInstance = this;}void OnDestroy() {mInstance = null;}
}

使用

public class DownloadDemo : MonoBehaviour {DownloadItem m_item;string testScrUrl = "http://dlsw.baidu.com/sw-search-sp/soft/ca/13442/Thunder_dl_7.9.42.5050.1449557123.exe";int count = 0;void Start() {Debug.Log(Application.persistentDataPath);//m_item = new WWWDownloadItem(testScrUrl, Application.persistentDataPath);//m_item.StartDownload(DownloadFinish);m_item = new HttpDownloadItem(testScrUrl, Application.persistentDataPath);m_item.StartDownload(DownloadFinish);}void Update() {count++;if(count % 20 == 0) {if(m_item != null && m_item.isStartDownload) {Debug.Log("下载进度------" + m_item.GetProcess() + "------已下载大小---" + m_item.GetCurrentLength());}}}void DownloadFinish() {Debug.Log("DownloadFinish!!!");}
}

unity 下载文件 断点续传相关推荐

  1. Unity下载文件的方式小结

    1 UnityWebRequest下载 unity自带的下载方式,优点很明显:封装很好,使用简便,与unity使用兼容性很好且跨平台问题少:对应的缺点:扩展性差. 1.1 存在内存中供程序使用或者下载 ...

  2. OC/Swift 技术 下载文件(断点续传 AFN下载文件 Alamofire下载文件 原生下载)(源码)

    一直觉得自己写的不是技术,而是情怀,一个个的教程是自己这一路走来的痕迹.靠专业技能的成功是最具可复制性的,希望我的这条路能让你们少走弯路,希望我能帮你们抹去知识的蒙尘,希望我能帮你们理清知识的脉络,希 ...

  3. AFNetworking 下载文件断点续传操作

    一:本示例代码包括: 文件下载,写入指定目录 下载进度,回调Progress; 断点续传,下载暂停,继续操作: 二:本项目 适用于 AFNetworking 1.x 版本 1 #pragma mark ...

  4. unity下载文件三(http异步下载)

    异步下载,顾名思义就是不影响你主线程使用客户端的时候,人家在后台搞你的明堂. 直接入主题,既然要下载,首先得请求,请求成功之后进行回调,这就是一个异步过程,异步回调的时间不可控. 1.首先请求下载. ...

  5. unity 下载文件到存放本地

    一.下载图片存放本地文件夹 public void DownloadFile() {WebClient webClient = new WebClient();//将图片下载到文件夹webClient ...

  6. Unity下载文件并显示进度

    public class ItemScript : MonoBehaviour {//异步对象 private WWW downloadOperation; // Use this for initi ...

  7. Unity UnityWebRequest下载文件 替代WWW

    今天测试那边提了个问题,就是当网络极差的时候,游戏下载将会停止(即一直在等待yield return www)当时间较长时网络恢复将无法继续下载,也没有提示,需要重启才能重新下载.因为WWW不存在设置 ...

  8. iOS开发之网络编程--使用NSURLConnection实现大文件断点续传下载

    前言:iOS开发之网络编程--使用NSURLConnection实现大文件断点续传下载是在前篇iOS开发之网络编程--使用NSURLConnection实现大文件下载的基础上进行    断点续传的设置 ...

  9. Android下载文件(一)下载进度断点续传

    Android下载文件(一)下载进度&断点续传 索引 Android下载文件(一)下载进度&断点续传 Android下载文件(二)单任务多线程并发&断点续传(待续) Andro ...

最新文章

  1. R语言Brown-Forsythe检验验证组间方差是否相等实战:执行Brown-Forsythe检验、如果各组间的方差不相等我们该怎么办(进行方差分析)
  2. gcc 复杂结构体 初始化_gcc编译选项
  3. windows下java环境搭建
  4. c语言链表把多少分以上打出来,大神帮我看一下怎么输入输出一个链表,我输入了但是没输出啊...
  5. 【云炬大学生创业基础笔记】第1章第4节 为什么需要创业测试
  6. html5+css3第一次作业_“台风爷爷,让我作业飞走!”南京小学生写的诗都这么逆天了?...
  7. windows安装dcm4chee 出错 check file system group LOSSY_STORAGE for deletion
  8. Jmeter上传文件
  9. 服务器_Windows Server 2012 服务器之Web服务器
  10. 2020教师计算机考试笔试题,2020年全国教师资格考试信息技术学科知识与能力练习题...
  11. unity3d 为什么要烘焙/unity3d 烘焙作用是为了什么【2020】
  12. python内置数值运算函数有哪几个_Python这68个内置函数,建议你吃透!
  13. POSCMS 网站设置
  14. windows系统无法保存文件的解决方案
  15. 最近用了一个免费的服务器
  16. 数据库管理 │ 浅谈从集中式到分布式数据库的转型要点
  17. 【GNSS】北斗坐标系
  18. 一个活了 45 年的愚蠢 Bug
  19. Hadoop 3.0的新增功能– Apache Hadoop 3的增强功能
  20. C++面试基础知识点

热门文章

  1. 煤矿生活区水泵房远程监控物联网系统
  2. 测试-http接口测试点
  3. C51单片机学习笔记之矩阵键盘
  4. 修改EMC VNX的管理口IP地址
  5. C++入狱日记001——用VScode+TDM GCC搭建C++环境
  6. 修复org.apache.jasper.JasperException: 无法编译JSP
  7. 电话招生技巧开场白---转载 (二)
  8. 51单片机c语言内存使用,51单片机C语言编程之内存优化
  9. TCP/IP协议学习记录之一:ppp适配器和以太网适配器
  10. 20230508在Ubuntu22.04下使用python3批量转换DOCX文档为TXT