Unity下实现断点续传的下载方式

直接上代码

主代码:

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using UnityEngine;

/// <summary>
/// 断点续传下载器
/// </summary>
public class Downloader
{
    /// <summary>
    /// 一个载单元
    /// </summary>
    public class DownloadUnit
    {
        public string downUrl;
        public string savePath;

        public DownloadUnit(string url, string path)
        {
            this.downUrl = url;
            this.savePath = path;
        }
    };

    const int oneReadLen = 16384;           // 一次读取长度 16384 = 16*kb
    const int ReadWriteTimeOut = 2 * 1000;  // 超时等待时间
    const int TimeOutWait = 5 * 1000;       // 超时等待时间
    const int MaxTryTime = 3;


    /// <summary>
    /// 批量下载
    /// 开线程
    /// </summary>
    /// <param name="list">下载列表</param>
    /// <param name="precentCallback">下载进度回调</param>
    public static void BatchDownload(List<DownloadUnit> list, System.Action<long, long, DownloadUnit> callback, System.Action<DownloadUnit> errorCallback = null)
    {
        EasyThread dwonloadThread = new EasyThread(()=>
        {
            download(list, callback, errorCallback);
        });
        dwonloadThread.Start();
    }

    /// <summary>
    /// 单个下载
    /// 开线程
    /// </summary>
    /// <param name="downUnit"></param>
    /// <param name="precentCallback">下载进度回调</param>
    public static void SingleDownload(DownloadUnit downUnit,System.Action<long, long> callback, System.Action<DownloadUnit> errorCallback = null)
    {
        EasyThread dwonloadThread = new EasyThread(()=>
        {
            download(downUnit, callback, errorCallback);
        });
        dwonloadThread.Start();
    }

    /// <summary>
    /// 下载
    /// </summary>
    /// <param name="downList"></param>
    /// <param name="callback"></param>
    static void download(List<DownloadUnit> downList, System.Action<long, long, DownloadUnit> callback, System.Action<DownloadUnit> errorCallback=null)
    {
        // 计算所有要下载的文件大小
        long totalSize = 0;
        long oneSize = 0;
        DownloadUnit unit;
        int i = 0;
        for (i=0; i< downList.Count; i++)
        {
            unit = downList[i];
            oneSize = GetWebFileSize(unit.downUrl);
            totalSize += oneSize;
        }

        long currentSize = 0;
        i = 0;
        int count = downList.Count;
        for (i = 0; i < count; i++)
        {
            //Debug.Log("iiiiiiii == " + i);
            unit = downList[i];
            long currentFileSize = 0;
            download(unit, (long _currentSize, long _fileSize) => {
                currentFileSize = _currentSize;
                long  tempCurrentSize = currentSize + currentFileSize;
                Debug.LogFormat("i = {0},tempCurrentSize = {1}, _fileSize = {2},currentSize = {3}, totalSize = {4}",
                    i, tempCurrentSize, _fileSize, currentSize, totalSize);
                if (callback != null) callback(tempCurrentSize, totalSize, unit);
            }, (DownloadUnit _unit) =>{
                if (errorCallback != null) errorCallback(_unit);
            });
            currentSize += currentFileSize;

            Debug.Log("finishe one: i = " + i);
        }
    }


    /// <summary>
    /// 下载
    /// </summary>
    /// <param name="downUnit"></param>
    /// <param name="callback"></param>
    static void  download(DownloadUnit downUnit, System.Action<long, long> callback, System.Action<DownloadUnit> errorCallback = null)
    {
        //打开上次下载的文件
        long startPos = 0;
        string tempFile = downUnit.savePath+".temp";
        FileStream fs = null;
        if (File.Exists(tempFile))
        {
            fs = File.OpenWrite(tempFile);
            startPos = fs.Length;
            fs.Seek(startPos, SeekOrigin.Current); //移动文件流中的当前指针

        }
        else
        {
            string direName = Path.GetDirectoryName(tempFile);
            if (!Directory.Exists(direName)) Directory.CreateDirectory(direName);
            fs = new FileStream(tempFile, FileMode.Create);
        }

        // 下载逻辑
        HttpWebRequest request = null;
        WebResponse respone = null;
        Stream ns = null;
        try
        {
            request = WebRequest.Create(downUnit.downUrl) as HttpWebRequest;
            request.ReadWriteTimeout = ReadWriteTimeOut;
            request.Timeout = TimeOutWait;
            if (startPos > 0) request.AddRange((int)startPos);  //设置Range值,断点续传
            //向服务器请求,获得服务器回应数据流
            respone = request.GetResponse();
            ns = respone.GetResponseStream();
            long totalSize = respone.ContentLength;
            long curSize = startPos;
            if (curSize == totalSize)
            {
                fs.Flush();
                fs.Close();
                fs = null;
                if (File.Exists(downUnit.savePath)) File.Delete(downUnit.savePath);
                File.Move(tempFile, downUnit.savePath);
                if (callback != null) callback(curSize, totalSize);
            }
            else
            {
                byte[] bytes = new byte[oneReadLen];
                int readSize = ns.Read(bytes, 0, oneReadLen); // 读取第一份数据
                while (readSize > 0)
                {
                    fs.Write(bytes, 0, readSize);       // 将下载到的数据写入临时文件
                    curSize += readSize;

                    // 判断是否下载完成
                    // 下载完成将temp文件,改成正式文件
                    if (curSize == totalSize)
                    {
                        fs.Flush();
                        fs.Close();
                        fs = null;
                        if (File.Exists(downUnit.savePath)) File.Delete(downUnit.savePath);
                        File.Move(tempFile, downUnit.savePath);
                    }

                    // 回调一下
                    if (callback != null) callback(curSize, totalSize);
                    // 往下继续读取
                    readSize = ns.Read(bytes, 0, oneReadLen);
                }
            }
        }
        catch (WebException ex)
        {
            if(errorCallback != null)
            {
                errorCallback(downUnit);
                Debug.Log("下载出错:" + ex.Message);
            }
        }
        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();
        }
    }

    /// <summary>
    /// 获取计算网络文件的大小
    /// </summary>
    /// <param name="url"></param>
    /// <returns></returns>
    public static long GetWebFileSize(string url)
    {
        HttpWebRequest request = null;
        WebResponse respone = null;
        long length = 0;
        try
        {
            request = WebRequest.Create(url) as HttpWebRequest;
            request.Timeout = TimeOutWait;
            request.ReadWriteTimeout = ReadWriteTimeOut;
            //向服务器请求,获得服务器回应数据流
            respone = request.GetResponse();
            length = respone.ContentLength;
        }
        catch (WebException e)
        {
            throw e;
        }
        finally
        {
            if (respone != null) respone.Close();
            if (request != null) request.Abort();
        }
        return length;
    }
}

测试代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestHttpManager : MonoBehaviour
{

    // Update is called once per frame
    void Update ()
    {
        if(Input.GetKeyUp(KeyCode.S))
        {
            Down_Single();
        }
        else if(Input.GetKeyUp(KeyCode.D))
        {
            Down_List();
        }
    }

    void Down_Single()
    {
        string downUrl = @"http://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1493218983354&di=1721b5368b88209b4fe671afd3f9102f&imgtype=0&src=http%3A%2F%2Fpic41.nipic.com%2F20140523%2F18507730_165953869000_2.jpg";
        string savePath = @"F:\projects\unity\BreakpointTransmission\download\file.jpg";
        Downloader.DownloadUnit unit = new Downloader.DownloadUnit(downUrl, savePath);
        Downloader.SingleDownload(unit, (currentSize, totalSize)=>
        {
            float percent = (currentSize / (float)totalSize) * 100;
            Debug.LogFormat("currentSize = {0}, totalSize = {1}, percent = {2}", currentSize, totalSize, percent.ToString("F2"));
            if(currentSize == totalSize)
            {
                Debug.Log("------------下载完成-----------");
            }
        },
        (downUnit)=>
        {
            Debug.Log("------------下载出错-----------");
        });
    }

    void Down_List()
    {
        string downUrl1 = @"http://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1493218983355&di=4db20f8769976f4df646d07c3545eeea&imgtype=0&src=http%3A%2F%2Fimg6.3lian.com%2Fc23%2Fdesk4%2F04%2F57%2Fd%2F10.jpg";
        string downUrl2 = @"http://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1493218983355&di=00af74a5435438d149dfbfa8f335fb63&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fforum%2Fpic%2Fitem%2F5d8ea144ad345982913052140cf431adcaef8455.jpg";
        string downUrl3 = @"http://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1493218983355&di=e925997036e582bac8875ccab462decc&imgtype=0&src=http%3A%2F%2Fattimg.dospy.com%2Fimg%2Fday_120706%2F20120706_a4ea28027b7545cd36a1Ku44Kt93sAPS.jpg";
        string downUrl4 = @"http://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1493218983355&di=5ab76db153e7b3af880e8354837ef09a&imgtype=0&src=http%3A%2F%2Fwww.bizhiwa.com%2Fuploads%2Fallimg%2F2012-01%2F20114H3-1-1M522.jpg";
        string downUrl5 = @"http://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1493218983355&di=205f4221df8463251686e7eb278bbda3&imgtype=0&src=http%3A%2F%2Fpic41.nipic.com%2F20140501%2F18539861_155959517170_2.jpg";
        string savePath1 = @"F:\projects\unity\BreakpointTransmission\download\file1.jpg";
        string savePath2 = @"F:\projects\unity\BreakpointTransmission\download\file2.jpg";
        string savePath3 = @"F:\projects\unity\BreakpointTransmission\download\file3.jpg";
        string savePath4 = @"F:\projects\unity\BreakpointTransmission\download\file4.jpg";
        string savePath5 = @"F:\projects\unity\BreakpointTransmission\download\file5.jpg";

        List<Downloader.DownloadUnit> list = new List<Downloader.DownloadUnit>();
        list.Add(new Downloader.DownloadUnit(downUrl1, savePath1));
        list.Add(new Downloader.DownloadUnit(downUrl2, savePath2));
        list.Add(new Downloader.DownloadUnit(downUrl3, savePath3));
        list.Add(new Downloader.DownloadUnit(downUrl4, savePath4));
        list.Add(new Downloader.DownloadUnit(downUrl5, savePath5));
        Downloader.BatchDownload(list, (currentSize, totalSize, unit) =>
        {
            float percent = (currentSize / (float)totalSize) * 100;
            //Debug.Log("percent:" + percent.ToString("F2") + "  file:"+ unit.savePath);
            if (currentSize == totalSize)
            {
                Debug.Log("------------下载完成-----------");
            }
        },
        (downUnit) =>
        {
            Debug.Log("------------下载出错-----------");
        });
    }
}

Unity工程:

[点击下载](http://download.csdn.net/detail/anyuanlzh/9827348)
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿海-程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值