C#写的异步文件下载器

C#写的异步文件下载器

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsAppDownloader
{
    public partial class FormDownloader : Form
    {
        public FormDownloader()
        {
            InitializeComponent();
            textBoxDownloadFolder.Text = Directory.GetCurrentDirectory();
            if (false)
            {
                List<string> list = new List<string>();
                list.Add(@"D:\Users\" + Environment.UserName);
                list.Add(@"C:\Users\" + Environment.UserName);
                list.Add(@"E:\Users\" + Environment.UserName);
                list.Add(@"F:\Users\" + Environment.UserName);
                list.Add(@"G:\Users\" + Environment.UserName);
                textBoxDownloadFolder.Text = CreateDirectory(list.ToArray(), "feieryun");
            }
        }

        public static string CreateDirectory(string[] folderPaths, string folderName)
        {
            foreach (string folderPath in folderPaths)
            {
                try
                {
                    // 在指定路径下尝试创建一个临时文件夹
                    string newFolder = Path.Combine(folderPath, folderName);
                    if (Directory.Exists(newFolder))
                    {
                        return newFolder;
                    }
                    Directory.CreateDirectory(newFolder);
                    return newFolder;
                }
                catch (Exception)
                {
                    // 如果没有创建子文件夹的权限,就继续检查下一个文件夹
                }
            }

            // 如果所有文件夹都没有创建子文件夹的权限,就返回 null
            return "";
        }

        public static void ChooseFolder(string SelectedPath, Func<string, Task> callback)
        {
            using (FolderBrowserDialog dialog = new FolderBrowserDialog())
            {
                dialog.SelectedPath = SelectedPath;
                DialogResult result = dialog.ShowDialog();
                if (result == DialogResult.OK)
                {
                    callback(dialog.SelectedPath);
                }
            }
        }

        private bool isDoingFlag = false;
        static HttpWebRequest CreateHttp(string url)
        {
            HttpWebRequest req = WebRequest.CreateHttp(url);
            req.UserAgent = "curl/7.76.1";
            return req;
        }

        async Task<string> getFilenameByURL(string url)
        {
            HttpWebRequest request = CreateHttp(url);
            request.Method = "GET";
            WebResponse response = await request.GetResponseAsync();
            response.Close();
            return getFilenameByHeader(response.Headers);
        }

        static string getFilenameByHeader(WebHeaderCollection Headers)
        {
            string contentDisposition = Headers["Content-Disposition"];
            if (!string.IsNullOrEmpty(contentDisposition))
            {
                int fileNameIndex = contentDisposition.IndexOf("filename=", StringComparison.InvariantCultureIgnoreCase);
                if (fileNameIndex >= 0)
                {
                    string fileName = contentDisposition.Substring(fileNameIndex + 9).Trim().TrimStart('"').TrimEnd('"');
                    return fileName;
                }
            }
            return "";
        }

        public async Task UrlDownloader(string url, string savePath, Func<long, long, Task> callback)
        {
            HttpWebRequest request = CreateHttp(url);
            FileStream output = new FileStream(savePath, FileMode.OpenOrCreate);
            long downloadPostion = output.Length;
            long downloadLength = 0;
            if (downloadPostion > 0)
            {
                // 如果这个文件之前下载过,就获取完整的文件大小
                HttpWebRequest headReq = CreateHttp(url);
                headReq.UserAgent = "curl/7.76.1";
                headReq.Method = "HEAD";
                WebResponse headRes = await headReq.GetResponseAsync();
                downloadLength = headRes.ContentLength;
                headRes.Close();
                if (downloadPostion == downloadLength)
                {
                    // 文件大小相同代表已经下载完成
                    await callback(downloadPostion, downloadLength);
                    output.Close();
                    return;
                }
                // 请求服务器从当前文件大小的位置开始下载
                request.AddRange(downloadPostion);
            }
            WebResponse response = await request.GetResponseAsync();
            if (downloadPostion == 0)
            {
                downloadLength = response.ContentLength;
            }
            output.Seek(downloadPostion, SeekOrigin.Begin);
            using (Stream input = response.GetResponseStream())
            {
                // 指定缓冲区大小
                byte[] buffer = new byte[1024 * 1024];
                while (isDoingFlag)
                {
                    int bytesRead = await input.ReadAsync(buffer, 0, buffer.Length);
                    if (bytesRead == 0)
                    {
                        // 读取到0字节代表下载已完成
                        break;
                    }
                    downloadPostion += bytesRead;
                    await callback(downloadPostion, downloadLength);
                    await output.WriteAsync(buffer, 0, bytesRead);
                }
            }
            output.Close();
            response.Close();
        }
        public static string FormatBytes(long bytes)
        {
            string[] sizes = { "B", "KB", "MB", "GB", "TB" };
            double len = bytes;
            int order = 0;
            while (len >= 1024 && order < sizes.Length - 1)
            {
                order++;
                len /= 1024;
            }
            return $"{len:0.##} {sizes[order]}";
        }

        private void buttonChooseFolder_Click(object sender, EventArgs e)
        {
            ChooseFolder(textBoxDownloadFolder.Text, async (string pathName) =>
            {
                textBoxDownloadFolder.Text = pathName;
            });
        }

        private async void buttonStartDownload_Click(object sender, EventArgs e)
        {
            buttonStartDownload.Enabled = false;
            buttonStopDownload.Enabled = true;
            isDoingFlag = true;
            string url = textBoxDownloadURL.Text;
            string filename = await getFilenameByURL(url);
            Uri uri = new Uri(url);
            if (string.IsNullOrEmpty(filename))
            {
                filename = uri.Segments[uri.Segments.Length - 1];
            }
            string savePath = Path.Combine(textBoxDownloadFolder.Text, filename);
            progressBar1.Maximum = 10000;
            await UrlDownloader(url, savePath, async (long postion, long total) =>
            {
                long aa = progressBar1.Maximum * postion / total;
                if (aa > progressBar1.Maximum)
                {
                    aa = progressBar1.Maximum;
                }
                progressBar1.Value = (int)aa;
                label_progress.Text = "正在下载 " + FormatBytes(postion) + " / " + FormatBytes(total);
            });
            buttonStartDownload.Enabled = true;
            buttonStopDownload.Enabled = false;
        }

        private void buttonStopDownload_Click(object sender, EventArgs e)
        {
            buttonStopDownload.Enabled = false;
            isDoingFlag = false;
        }
    }



}

 

posted on 2023-05-13 10:53  项希盛  阅读(241)  评论(0)    收藏  举报