雪千渔Blog

  • 首页
  • 写写代码
    • dotNet
    • C++
    • Lua
    • Visual Basic
    • Java
    • Android
    • Web
  • DCC
    • Maya
    • Maya-Plug
    • AfterEffect
    • AfterEffect-Plug
    • PhotoShop-Plug
  • 游戏制作
    • Unity3D
    • UnrealEngine
    • 经验杂谈
    • 游戏设计
    • 自研引擎
    • 效果实现
  • 其他
    • 乱七八糟
    • 软件工具
    • 留言板
    • 自制素材
    • 关于我
  • 世界的尽头
雪千渔blog
唯有热爱,能抵漫长岁月
  1. 首页
  2. Coding
  3. dotNet
  4. 正文

C#之支持断点续传的下载器

2019年3月24日 3478点热度 1人点赞 0条评论

该下载模块总共会多开两个线程,一个下载线程和一个计时器线程,计时器线程主要用来计算每秒的下载速度。考虑版本兼容的问题没用使用await/async,而是使用传统的Thread。

用法:

Downloader d = new Downloader();
d.SetTask("https://dl.360safe.com/setup.exe", @"F:\360.exe");
d.Start();
//当下载线程下载完毕后记得调用
d.Dispose();

源代码:
using System;
using System.IO;
using System.Net;
using System.Threading;


namespace com.imxqy.net
{
    public sealed class Downloader : IDisposable
    {
        public enum DownloadState
        {
            None,
            Download,
            Pause,
            Finish,
        }
        //目标文件地址
        public string TargetURL { get; private set; }
        //目标文件大小
        public long TargetLength { get; private set; }
        //下载的本地文件路径
        public string LocalFilePath { get; private set; }
        //已经下载的本地文件大小
        public long DownloadedLength { get; private set; }
        //下载速度
        public int Speed { get; private set; }
        private long lastDownloadLength;
        private Timer timer;

        private DownloadState state = DownloadState.None;
        public DownloadState State
        {
            get => this.state;
            private set
            {
                this.state = value;
                this.StateHandler?.Invoke(value);
            }
        }

        //状态委托
        public event Action<DownloadState> StateHandler;

        //下载时的文件名
        private string downloadingName = string.Empty;
        //下载时的额外后缀名
        private const string DOWNLOADING_FILE_EXT = ".jxdown";

        private Thread downloadThread = null;
        //设置下载任务
        public void SetTask(string targetURL, string localPath)
        {
            this.Reset();
            this.TargetURL = targetURL;
            this.LocalFilePath = localPath;
        }
        //重置
        private void Reset()
        {
            this.State = DownloadState.None;
            this.DownloadedLength = 0;
            this.lastDownloadLength = 0;
            this.Speed = 0;
        }
        //开始
        public void Start()
        {
            if (this.State == DownloadState.Download)
                return;

            this.State = DownloadState.Download;

            if (this.downloadThread == null)
            {
                this.downloadThread = new Thread(this.DownloadThread);
            }

            //开启下载线程
            this.downloadThread.IsBackground = false;
            this.downloadThread.Start(this);

            //开启速度计时器线程
            if (this.timer == null)
            {
                this.timer = new Timer((sender) =>
                {
                    Downloader self = (Downloader)sender;
                    var distance = self.DownloadedLength - self.lastDownloadLength;
                    self.Speed = (int)distance;
                    self.lastDownloadLength = self.DownloadedLength;
                }, this, -1, 0);
            }

            this.timer.Change(0, 1000);
        }
        //下载线程
        private void DownloadThread(object _this)
        {
            Downloader self = (Downloader)_this;

            self.downloadingName = self.LocalFilePath + DOWNLOADING_FILE_EXT;

            if (File.Exists(self.LocalFilePath))
            {
                //TODO 下载完成
                self.State = DownloadState.Finish;
                return;
            }
            //获取长度
            self.TargetLength = Http.GetHttpFileLenght(self.TargetURL);
            //获取远程文件流
            HttpWebRequest httpWebRequest = HttpWebRequest.Create(self.TargetURL) as HttpWebRequest;


            //本地文件流
            FileStream fs = null;
            if (File.Exists(self.downloadingName))
            {
                //断点续传
                fs = new FileStream(self.downloadingName, FileMode.Open);
                self.DownloadedLength = fs.Length;
                //移动指针
                fs.Seek(fs.Length, SeekOrigin.Current);
                //请求续传
                httpWebRequest.AddRange(fs.Length);
            }
            else
            {
                //创建新文件
                fs = new FileStream(self.downloadingName, FileMode.Create);
            }

            //下载
            Stream downStream = httpWebRequest.GetResponse().GetResponseStream();

            const int chunkSize = 409600; // 400kb
            byte[] buf = new byte[chunkSize];

            int size = 0;

            while (self.state == DownloadState.Download && (size = downStream.Read(buf, 0, chunkSize)) > 0)
            {
                //写文件流
                fs.Write(buf, 0, size);
                fs.Flush();
                self.DownloadedLength += size;
            }

            fs.Close();
            downStream.Close();

            self.Finish();
        }

        private void Finish()
        {
            File.Move(this.downloadingName, this.LocalFilePath);
            this.State = DownloadState.Finish;
        }

        public void Pause()
        {
            this.State = DownloadState.Pause;
            this.timer.Change(-1, 0);
        }

        public void Dispose()
        {
            if (this.downloadThread != null)
            {
                this.downloadThread.Abort();
                this.downloadThread = null;
            }
            this.timer.Dispose();
            this.timer = null;
            GC.SuppressFinalize(this);
        }
    }

}

 

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: C# 下载器
最后更新:2020年6月27日

JomiXedYu

一名游戏玩家。

点赞
< 上一篇
下一篇 >

文章评论

取消回复

*

code

JomiXedYu

一名游戏玩家。

分类
  • AfterEffect / 6篇
  • AfterEffect-Plug / 1篇
  • Android / 1篇
  • C++ / 13篇
  • dotNet / 12篇
  • Lua / 4篇
  • Maya / 2篇
  • Maya-Plug / 1篇
  • Office-VSTO&VBA / 2篇
  • Unity3D / 14篇
  • UnrealEngine / 1篇
  • Visual Basic / 8篇
  • Web / 2篇
  • 乱七八糟 / 2篇
  • 效果实现 / 2篇
  • 经验杂谈 / 2篇
  • 自制素材 / 3篇
  • 计算机图形学 / 1篇
  • 软件工具 / 4篇
友情链接
  • DorinXL
  • 小博博客
  • 秋橘斋

COPYRIGHT © 2014-2021 雪千渔Blog. ALL RIGHTS RESERVED.

THEME KRATOS MADE BY VTROIS

辽ICP备20006894号-1