文档章节

下载器断点下载-方便游戏强更

梦想游戏人
 梦想游戏人
发布于 08/09 12:36
字数 1579
阅读 43
收藏 1

Unity下的版本,设计是游戏内嵌 一个下载器 下载 游戏 方便游戏强更

using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Net;
using UnityEngine;
using System.IO;
using System;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Collections.Specialized;
using System.Reflection;

namespace Patches2
{
    //just android suport  IOS直接跳转app-store 即可
    //用于游戏内置的下载器 下载
    public class MAX_VERSION
    {
        public string Version = "";
        public string MD5 = "";
        public int FileSize = 5000;//这个file size 只是给玩家看的 实际下载 不用到该变量
        public string Url = "";
        public string RollBackUrl = "";//下载回滚页面 比如下载fatal error 会直接opel url 
        //this data is legal or illegal 
        public bool IsLegal()
        {
            if (Version != null && MD5 != null && FileSize > 0 && Url != null)
            {
                if (Version.Length >= 5 && MD5.Length > 0 && Url.Length > 5)
                {
                    return true;
                }
            }
            return false;
        }
    }


    //安装包下载器 支持断点续传 支持游戏内置 下载  下载完成后 调用native api进行安装
    //其实只需要android 平台即可 IOS直接跳转 app-store
    public class InstallerDownloader
    {
        //下载的 apk 存放名字
        public const string ApkName = "hcr.apk";
        //调用该函数 开始安装  只能在 unity主线程调用
        public static void StartInstallApk(string full_file_path)
        {
#if UNITY_ANDROID
            NativeApi.InstallApk(full_file_path);
#endif
        }
        public enum Status
        {
            None = 0,//未知
            Error, // 下载错误  或者超时 
            Downloading, // 下载中  外部可以读取静态变量 来显示下载进度
            Checking,// 处理 下载前逻辑中
            Verifying, // 校验文件中 可能是下载前 可能是下载后
            OK,//下载完成 可以开始执行安装操作了
        }
        public class DownloadParam
        {
            public string url;
            public string path_to_save;
            public string file_name;
            public bool enable_break_point;//是否开启断点续传功能
            public string md5;//md5 用于校验安装包的完整性
            public bool IsRedirect = false;//是否是重定向 是重定向的话 会忽略 失败次数统计
        }
        Thread t_download = null;
        public void Terminal()
        {
            if (t_download != null)
            {
                try
                {
                    t_download.Abort();
                }
                catch (Exception e)
                {
                    Debug.LogWarning(e.Message);
                }
                t_download = null;
            }
            CurrentSize = 0;
            TotalSize = 0;
            _Status = Status.None;
        }
        // 需要下载的大小  内部减去了 断点续传的 部分
        public static int GetLeftSize(string path_to_save, string file_name, int total_size)
        {
            string full_path = path_to_save + "/" + file_name;
            if (File.Exists(full_path))
            {

                var info = new FileInfo(full_path);
                if (info != null)
                {
                    if (total_size < info.Length)
                    {
                        try
                        {
                            File.Delete(full_path);
                        }
                        catch (Exception e)
                        {

                        }
                        return total_size;
                    }
                    else
                    {
                        return total_size - (int)info.Length;
                    }
                }
            }
            return total_size;
        }
        //改变量只能在 unity主线程调用
        public static string InstallRootDir
        {
            get
            {
#if !UNITY_EDITOR
                return Application.persistentDataPath + "/Installer";
#else
                return "Installer";
#endif
            }
        }
        public void StartDownload(string url, string path_to_save, string file_name, string md5, bool enable_break_point = true)
        {
            if (t_download != null)
            {
                try
                {
                    t_download.Abort();
                }
                catch (Exception e)
                {
                    Debug.LogWarning(e.Message);
                }
            }
            t_download = new Thread(new ParameterizedThreadStart(ThreadFunc));
            IsThreadRunning = true;
            DownloadParam _param = new DownloadParam
            {
                url = url,
                path_to_save = path_to_save,
                file_name = file_name,
                enable_break_point = enable_break_point,
                md5 = md5
            };
            try_times = 0;
            _Status = Status.Checking;
            t_download.Start(_param);
        }
        bool IsThreadRunning = false;

        public static Status _Status = Status.None;
        public int HttpRetCode = 0;

        public static int TotalSize = 0; // 总大小
        public static int CurrentSize = 0; // 当前大小 可用于进度显示

        int try_times = 0;


        private void DownloadOK()
        {
            _Status = Status.OK;

            //开始安装流程  调用native api 开始安装
            Debug.LogWarning("download ok");

        }

        private void ThreadFunc(object _param_call)
        {
            CurrentSize = 0;
            TotalSize = 0;
            Debug.LogWarning("start to download");


            DownloadParam _param = _param_call as DownloadParam;
            if (_param == null)
            {
                IsThreadRunning = false;
                _Status = Status.Error;
                return;
            }
            if (_param.IsRedirect)
            {
                //重定向的话 不处理 失败 重试次数
                _param.IsRedirect = false;
            }
            else
            {
                //重新下载 或者 分批下载 都会重试计次
                ++try_times;
            }
            if (try_times > 10)
            {
                //fatal error or net error
                _Status = Status.Error;
                return;
            }
            try
            {
                _Status = Status.Verifying;
                if (File.Exists(_param.path_to_save + "/" + _param.file_name))
                {
                    //文件存在的话 检查一下 是否成功  不成功的话 才开始下载
                    _Status = Status.Verifying;
                    if (string.IsNullOrEmpty(_param.md5) == false && _param.md5 == Patches.MD5Code.GetMD5HashFromFile(_param.path_to_save + "/" + _param.file_name))
                    {
                        //ok
                        _Status = Status.OK;
                        this.DownloadOK();
                        return;
                    }
                    else
                    {
                        //md5 verify error 需要处理下载 (or断点下载) 下载完成后 才 再次校验
                    }
                }
            }
            catch (Exception e)
            {

            }
            _Status = Status.Checking;

            if (_param.enable_break_point == false)
            {
                //无需断点下载 尝试暴力删除文件
                try
                {
                    Directory.Delete(_param.path_to_save, true);
                }
                catch (Exception e)
                {
                    Debug.LogWarning(e.Message);
                }
            }
            if (Directory.Exists(_param.path_to_save) == false)
            {
                try
                {
                    Directory.CreateDirectory(_param.path_to_save);
                }
                catch (Exception e)
                {
                    Debug.LogWarning(e.Message);
                }
            }
            //先打开文件
            Stream file = null;
            using (file = (File.Exists(_param.path_to_save + "/" + _param.file_name)) ? File.OpenWrite(_param.path_to_save + "/" + _param.file_name) : file = File.Create(_param.path_to_save + "/" + _param.file_name))
            {
                /*  try
                  {
                      if (File.Exists(_param.path_to_save + "/" + _param.file_name))
                      {
                          file = File.OpenWrite(_param.path_to_save + "/" + _param.file_name);
                      }
                      else
                      {
                          file = File.Create(_param.path_to_save + "/" + _param.file_name);
                      }
                  }
                  catch (Exception e)
                  {
                      Debug.LogWarning(e.Message);
                  }*/
                try
                {
                    long current_size = file.Length;
                    if (current_size > 0)
                    {
                        file.Seek(current_size, SeekOrigin.Begin);
                    }
                    HttpWebRequest request = null;

                    //如果是发送HTTPS请求  
                    if (_param.url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
                    {
                        ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
                        request = (HttpWebRequest)WebRequest.Create(_param.url);
                    }
                    else
                    {
                        request = (HttpWebRequest)WebRequest.Create(_param.url);
                    }
                    request.ProtocolVersion = new System.Version(1, 1);
                    if (current_size > 0)
                    {
                        request.AddRange((int)current_size);
                        CurrentSize = (int)current_size;
                    }
                    HttpWebResponse response = null;
                    request.Timeout = 5000;
                    request.ReadWriteTimeout = 5000;
                    request.Method = "GET";
                    request.KeepAlive = false;
                    response = (HttpWebResponse)request.GetResponse();

                    var HttpRetCode = response.StatusCode;
                    Debug.Log("InstallDownloader http " + HttpRetCode);


                    if (HttpRetCode == HttpStatusCode.Redirect)
                    {
                        //重定向
                        _param.url = response.Headers["Location"].Trim();
                        response.Close();
                        response = null;
                        request.Abort();
                        request = null;
                        try
                        {
                            file.Close();
                        }
                        catch (Exception e)
                        {
                            Debug.LogWarning(e.Message);
                        }
                        Debug.Log("Redirect " + _param.url);
                        _param.IsRedirect = true;
                        ThreadFunc(_param);
                        return;

                    }
                    else if (HttpRetCode == HttpStatusCode.GatewayTimeout || HttpRetCode == HttpStatusCode.RequestTimeout)
                    {
                        //net error
                        response.Close();
                        response = null;
                        request.Abort();
                        request = null;
                        try
                        {
                            file.Close();
                        }
                        catch (Exception e)
                        {
                            Debug.LogWarning(e.Message);
                        }
                        Debug.Log("timeout");

                        return;

                    }
                    else if (HttpRetCode == HttpStatusCode.OK || HttpRetCode == HttpStatusCode.Created || HttpRetCode == HttpStatusCode.Accepted || HttpRetCode == HttpStatusCode.NonAuthoritativeInformation || HttpRetCode == HttpStatusCode.NoContent || HttpRetCode == HttpStatusCode.ResetContent || HttpRetCode == HttpStatusCode.PartialContent)
                    {
                        if (HttpRetCode != HttpStatusCode.PartialContent)
                        {
                            //如果不是断点下载 或者服务器不支持 那么需要 重新下载完整文件
                            try
                            {
                                file.Close();
                                file = null;
                            }
                            catch (Exception e)
                            {
                            }
                            try
                            {
                                Directory.Delete(_param.path_to_save, true);
                            }
                            catch (Exception e)
                            {
                            }
                            try
                            {
                                Directory.CreateDirectory(_param.path_to_save);
                            }
                            catch (Exception e)
                            {
                            }
                            file = File.Create(_param.path_to_save + "/" + _param.file_name);
                        }
                    }
                    else
                    {
                        //req error
                        response.Close();
                        response = null;
                        request.Abort();
                        request = null;
                        try
                        {
                            file.Close();
                        }
                        catch (Exception e)
                        {
                            Debug.LogWarning(e.Message);
                        }
                        Debug.LogWarning("error");
                        return;
                    }

                    //web 请求处理完成了 开始处理 接受数据了
                    long total_len = response.ContentLength;

                    TotalSize = (int)total_len + (int)current_size;
                    if (current_size < TotalSize)
                    {
                        if (current_size > 0)
                        {
                            //   request.AddRange((int)current_size);
                            CurrentSize = (int)current_size;
                        }
                        Stream web = request.GetResponse().GetResponseStream();
                        byte[] _cache = new byte[10240]; // 10kb
                        int down_size = 0;
                        int read_size = web.Read(_cache, 0, 10240);
                        int total_read_size = 0;
                        _Status = Status.Downloading;
                        while (read_size > 0)
                        {
                            _Status = Status.Downloading;
                            file.Write(_cache, 0, read_size);
                            total_read_size += read_size;

                            down_size += read_size;
                            CurrentSize += read_size;
                            //    Debug.LogError("download ing " + CurrentSize + "         " + TotalSize);
                            file.Flush();
                            read_size = web.Read(_cache, 0, 10240);
                        }
                        file.Close();
                        file = null;
                        web.Close();
                        web = null;
                        response.Close();
                        response = null;
                        request.Abort();
                        request = null;


                        if (current_size + down_size < TotalSize)
                        {
                            //下载文件 长度不够 需要重新下载
                            Debug.LogWarning("file is smaller will re-try");
                            ThreadFunc(_param);
                            return;
                        }
                        else if (current_size + down_size > TotalSize)
                        {
                            //下载的长度 超过了 实际长度 文件已经损坏 重新下载把
                            try
                            {
                                Directory.Delete(_param.path_to_save, true);
                            }
                            catch (Exception e)
                            {
                                Debug.LogWarning(e.Message);
                            }
                            Debug.LogWarning("file is bigger will delete and re-download");

                            ThreadFunc(_param);
                            return;
                        }
                        else
                        {
                            //下载文件成功 开始校验MD5
                            _Status = Status.Verifying;

                            if (string.IsNullOrEmpty(_param.md5) == false && _param.md5 == Patches.MD5Code.GetMD5HashFromFile(_param.path_to_save + "/" + _param.file_name))
                            {
                                //ok
                            }
                            else
                            {
                                //md5 verify error 尝试重新下载
                                try
                                {
                                    file.Close();
                                    file = null;
                                    response.Close();
                                    response = null;
                                    request.Abort();
                                    request = null;
                                }
                                catch (Exception e)
                                {
                                }
                                try
                                {
                                    Directory.Delete(_param.path_to_save, true);
                                }
                                catch (Exception e)
                                {
                                    Debug.LogWarning(e.Message);
                                }
                                ThreadFunc(_param);
                                return;
                            }
                            _Status = Status.OK;
                        }
                    }
                    else if (current_size == total_len)
                    {//当前文件和 服务器文件大小一样 默认为 下载完成 需要校验MD5

                        try
                        {
                            file.Close();
                            file = null;
                            response.Close();
                            response = null;
                            request.Abort();
                            request = null;
                        }
                        catch (Exception e)
                        {
                        }
                        Debug.LogWarning("file is  req just done");
                        _Status = Status.Verifying;

                        if (string.IsNullOrEmpty(_param.md5) == false && _param.md5 == Patches.MD5Code.GetMD5HashFromFile(_param.path_to_save + "/" + _param.file_name))
                        {
                            //ok
                        }
                        else
                        {
                            //md5 verify error 尝试重新下载
                            try
                            {
                                file.Close();
                                file = null;
                                response.Close();
                                response = null;
                                request.Abort();
                                request = null;
                            }
                            catch (Exception e)
                            {
                            }
                            try
                            {
                                Directory.Delete(_param.path_to_save, true);
                            }
                            catch (Exception e)
                            {
                                Debug.LogWarning(e.Message);
                            }
                            ThreadFunc(_param);
                            return;
                        }
                        _Status = Status.OK;
                    }
                    else
                    {
                        //当前文件超过了 大小 需要重新下载
                        try
                        {
                            Directory.Delete(_param.path_to_save, true);
                        }
                        catch (Exception e)
                        {
                            Debug.LogWarning(e.Message);
                        }
                        Debug.LogWarning("file is bigger will delete and re-download  2");

                        try
                        {
                            file.Close();
                            file = null;
                            response.Close();
                            response = null;
                            request.Abort();
                            request = null;
                        }
                        catch (Exception e)
                        {
                        }

                        ThreadFunc(_param);
                        return;
                    }
                    //走到了这里 都当作文件下载成功 并且校验成功 可以开始安装了
                    _Status = Status.OK;
                    this.DownloadOK();
                }
                catch (Exception ee)
                {
                    //整个下载流程出了异常错误 
                    Debug.LogWarning(ee.Message);
                    _Status = Status.Checking;
                    try
                    {
                        if (file != null)
                        {
                            file.Close();
                            file = null;
                        }
                    }
                    catch (Exception e)
                    {
                        Debug.LogWarning(e.Message);
                    }
                    ThreadFunc(_param);
                    return;
                }
            }
        }
        private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {
            return true;
        }
    }
}

 

© 著作权归作者所有

共有 人打赏支持
梦想游戏人
粉丝 36
博文 433
码字总数 123540
作品 0
成都
私信 提问
Ellan/StarForce

官方网站 简体中文 - http://gameframework.cn/ QQ 讨论群 216332935 Star Force 简介 Star Force 是一个使用 Game Framework 游戏框架制作的游戏演示项目,主要目的是对 Game Framework 的使...

Ellan
05/12
0
0
开发只懂 AFN ?搞定 NSURLSession 才是硬道理

由于傲娇的苹果在 iOS9 之后已经放弃了 NSURLConnection,所以在现在的实际开发中,除了大家常见的 AFN 框架,一般使用的是 iOS7 之后推出的 NSURLSession,作为一名 iOS 开发人员,如果你只...

秦无炎
2016/10/20
13
0
怎么下载优酷,土豆、乐视网上视频,4种快速方法

大家平时在优酷看电视,看到好的视频就想下载,尤其是一些学习教程,下面是总结的四种方法,很实用! 1、手动下载,以IE、Firefox为例IE:在IE中播放视频,然后进入C:Documents and Setting...

西西爱OS
2013/01/20
0
0
使用 Unity 3D 开发游戏的架构设计难点

http://geek.csdn.net/news/detail/135019 Unity 3D 引擎对于开发者来说,入手非常快,因为它采用的是 C# 作为开发语言,这也大大降低了开发者的门槛。但凡只要懂一门编程语言的人都能使用 ...

OnafioO
2017/01/20
0
0
从放弃迅雷和IDM到自己开发下载工具

前言 在这个网络带宽飞速增长的年代,下载文件要充分利用好网速就得用到下载工具,比如迅雷、IDM。然而贫穷限制了下载速度,这两个下载软件不花钱毫无体验可言。本人两年迅雷年费会员在离线下...

mklee
2017/12/08
0
0

没有更多内容

加载失败,请刷新页面

加载更多

day150-2018-11-17-英语流利阅读-待学习

歪果仁也疯狂:海外版抖音的征途 毛西 2018-11-17 1.今日导读 海外版抖音 TikTok 于 2017 年 5 月上线海外,至今覆盖全球 150 多个国家和地区,月活跃用户数已突破 5 亿。然而,“出海”的抖...

飞鱼说编程
今天
4
0
分布式学习最佳实践:从分布式系统的特征开始(附思维导图)

什么是分布式系统 回到顶部   分布式系统是由一组通过网络进行通信、为了完成共同的任务而协调工作的计算机节点组成的系统。分布式系统的出现是为了用廉价的、普通的机器完成单个计算机无法...

dragon_tech
今天
4
0
TOKEN设计

TOKEN设计 Api_Token 首先需要知道API是什么? API(Application Programming Interface)即应用程序接口。你可以认为 API 是一个软件组件或是一个 Web 服务与外界进行的交互的接口。而我们在...

DrChenXX
今天
3
0
浅谈“李氏代换”——从纪念金庸和斯坦李说起

李氏代换(LSP)简介 李氏代换是软件设计的一个原则,又名依赖倒转原则或依赖倒置原则,其衍生原则有接口分离原则等。该原则由Barbara Liskov于1988年提出。 该原则指出,程序中高级别的元素...

SamYjy
今天
33
0
JavaScript实现在线websocket WSS测试工具 -toolfk程序员工具网

本文要推荐的[ToolFk]是一款程序员经常使用的线上免费测试工具箱,ToolFk 特色是专注于程序员日常的开发工具,不用安装任何软件,只要把内容贴上按一个执行按钮,就能获取到想要的内容结果。T...

toolfk
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部