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();
        }
    }
}

 

原文地址:https://blog.csdn.net/qq_35436635/article/details/117680913  

posted @ 2022-04-24 11:20  一万年以前  阅读(670)  评论(0编辑  收藏  举报