C#多线程下载大文件

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SingleDownloader
{
    class DownloadingInformation
    {
        public int blocks { get; set; }
        public int finished { set; get; }
        public DownloadingInformation(int blocks,int finished)
        {
            this.blocks = blocks;
            this.finished = finished;
        }
    }

    class PartialInformation
    {
        public string url { get; set; }
        public long start { get; set; }
        public long end { set; get; }
        public PartialInformation(string url,long start,long end)
        {
            this.url = url;
            this.start = start;
            this.end = end;
        }

    }

    class DownloadInformation
    {
        public string link { get; set; }
        public string storeDir { get; set; }
        public string fileName { get; set; }
        public DownloadInformation(string link, string dir)
        {
            this.link = link;
            this.storeDir = dir;
            this.fileName = link.Split('/').Last<string>();
        }
        public DownloadInformation(string link, string dir, string fileName)
        {
            this.link = link;
            this.storeDir = dir;
            this.fileName = fileName;
        }

        
        public override string ToString()
        {
            return string.Format("link:{0} storeDir:{1} fileName:{2}", link, storeDir, fileName);
        }
    }
    class Program
    {
        //下载信息
        private static DownloadInformation downloadInformation;
        //下载过程中的信息,包括进度等
        private static DownloadingInformation downloadingInformation;
        //多线程锁
        private static ManualResetEvent manualResetEvent;

        private static long getSize(string url)
        {
            HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(url);
            httpWebRequest.AddRange(0, 1);
            HttpWebResponse response = (HttpWebResponse)httpWebRequest.GetResponse();
            string contentRange=response.Headers.Get("Content-Range");
            long res = long.Parse(contentRange.Split('/').Last<string>());
            response.Close();
            return res;
        }

        private static void partialDownload(Object param)
        {
            PartialInformation info = param as PartialInformation;
            HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(info.url);
            httpWebRequest.AddRange(info.start, info.end);
            HttpWebResponse response = (HttpWebResponse)httpWebRequest.GetResponse();
            var stream=response.GetResponseStream();
            FileStream fstream = new FileStream(downloadInformation.storeDir+"/"+downloadInformation.fileName, FileMode.Open,FileAccess.Write,FileShare.Write);
            fstream.Seek(info.start,SeekOrigin.Begin);
            byte[] content = new byte[1024];
            int len = 0;
            while((len= stream.Read(content, 0, 1024)) > 0)
            {
                fstream.Write(content, 0, len);
            }
            stream.Close();
            fstream.Close();
            response.Close();
            Console.SetCursorPosition(0, Console.CursorTop);
            Console.Write("已下载:{0}/{1}MB",++downloadingInformation.finished, downloadingInformation.blocks);
            if (downloadingInformation.finished == downloadingInformation.blocks)
                //通知主线程结束
                manualResetEvent.Set();
        }

        static void Main(string[] args)
        {
            downloadInformation = new DownloadInformation(args[0], args[1], args[2]);

            long size = getSize(downloadInformation.link);
            Console.WriteLine("总大小:{0}字节",size);
            ThreadPool.SetMinThreads(10, 10);
            ThreadPool.SetMaxThreads(20, 20);
            FileStream file = File.Create(downloadInformation.storeDir + "/" + downloadInformation.fileName);
            file.Close();
            downloadingInformation=new DownloadingInformation((int)Math.Ceiling(size / 1048576.0),0);
            for (long i = 0; i < downloadingInformation.blocks; i++)
            {
                var ii = new PartialInformation(downloadInformation.link, 1048576 * i, 1048576 * (i + 1) - 1);
                ThreadPool.QueueUserWorkItem(partialDownload, ii);
            }
            manualResetEvent = new ManualResetEvent(false);
            //阻塞主线程,等待所有子线程完成
            manualResetEvent.WaitOne();
        }
    }
}

接收3个参数,第一个是下载链接,第二个是存储文件夹,第三个是文件名称

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
C#中实现多线程下载文件的方法可以使用多线程技术和Http协议。首先,你可以创建一个MultiDownload类,该类接受线程数量、下载链接和保存路径作为参数。然后,在MultiDownload类中,你可以使用HttpWebRequest和HttpWebResponse类来发送HTTP请求并获取响应。你可以使用ContentLength属性获取下载文件的总长度,并使用AddRange方法指定每个线程下载文件数据范围。例如,request.AddRange(500, 1000)表示下载的范围为从500字节开始到1000字节处结束。[3] 在实现多线程下载时,你可以将下载任务分配给多个线程,并使用线程池或自定义线程来执行下载任务。你可以使用System.Threading命名空间中的Thread类来创建和管理线程。在每个线程中,你可以使用HttpWebRequest和HttpWebResponse类来下载文件的一部分,并将其保存到指定的路径中。你可以使用System.IO命名空间中的FileStream类来创建和写入文件。 在实现断点续传时,你可以在每次下载之前检查是否存在临时文件。如果存在临时文件,你可以获取临时文件的大小,并将各个临时文件的结束字节位置作为各个下载线程此次下载的起始位置。这样,当你再次打开程序时,可以从上次下载的位置继续下载文件。[2] 总结起来,你可以使用C#中的多线程技术和Http协议来实现多线程下载文件,并通过检查临时文件的存在和大小来实现断点续传功能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值