首页 > 编程语言 >C#写的异步文件下载器

C#写的异步文件下载器

时间:2023-05-13 11:01:07浏览次数:47  
标签:异步 return string C# await url downloadPostion using 下载

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



}

 

标签:异步,return,string,C#,await,url,downloadPostion,using,下载
From: https://www.cnblogs.com/xiangxisheng/p/17396941.html

相关文章

  • 小白学前端--001 VSCode安装+插件+字号调节
    工于利其事必先利其器,学前端工具选择很重要。一、VSCode是不错的选择。安装步骤不再赘述,一路下一步即可。vscode折叠左侧窗口,ctrl+B二、插架选择1、OpeninBrowser  (在代码中右键选择,在默认浏览器查看代码执行效果)2、Chinese(Simplified)(简体中文)......
  • 信捷PLC与7台三菱变频器485通讯案例功能:用信捷PLC与7台三菱变频器modbus通讯,自由通讯
    信捷PLC与7台三菱变频器485通讯案例功能:用信捷PLC与7台三菱变频器modbus通讯,自由通讯协议配件:信捷XC系列PLC,三菱E740变频器,昆仑通态触摸屏功能:对7台变频器进行单独频率设定,启停控制,频率读取。有参数设置,接线方式说明备注:只是程序,非硬件,程序有注释,欢迎选购ID:7745594342358096......
  • 昆仑通态屏与欧姆龙PLC和台达变频器联合控制通讯功能:用触摸屏与欧姆龙PLC进行通讯,同时
    昆仑通态屏与欧姆龙PLC和台达变频器联合控制通讯功能:用触摸屏与欧姆龙PLC进行通讯,同时与变频器直接进行通讯控制,触摸屏做为上位机配件:昆仑通态触摸屏,欧姆龙CP1HPLC,台达VFDM变频器说明:触摸屏与PLC进行通讯,同时与变频器进行频率的设定,读取电流电压值,控制启停,触摸屏做为上位机。只......
  • 三菱FX3U与4台台达变频器通讯说明:用三菱FX3U的PLC实现与4台台达变频器modbus通讯
    三菱FX3U与4台台达变频器通讯说明:用三菱FX3U的PLC实现与4台台达变频器modbus通讯器件:三菱FX3UPLC,三菱FX3U485BD通讯板,台达VFD-M变频器,昆仑通态触摸屏,附送威纶通触摸屏程序功能:触摸屏上设置每台频率,监控每台输出频率,输出电压,输出电流,控制启停,正反转。说明:已经通过测试运行可行。......
  • 昆仑通态MCGS与三菱FX3U 485BD方式通讯案例功能:实现昆仑通态触摸屏与三菱FX3U的485BD
    昆仑通态MCGS与三菱FX3U485BD方式通讯案例功能:实现昆仑通态触摸屏与三菱FX3U的485BD板通过485方式进行连接,而PLC的编程口同时又能与电脑连接,进行程序下载监控。器件:三菱FX3UPLC,三菱FX3U485BD板,昆仑通态触摸屏说明:是程序,非硬件YID:5425598566207994......
  • MacOS祖传bug
    问题:/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/stdlib.h:20:15:fatalerror:'stdlib.h'filenotfound#include_next<stdlib.h>^~~~~~~~~~1errorgenerated.error:command'/Librar......
  • 台达PLC与三菱E740或D700变频器modbus 通讯案例 配件:台达DVP系列PLC,
    台达PLC与三菱E740或D700变频器modbus通讯案例配件:台达DVP系列PLC,三菱E740或者d700变频器,昆仑通态触摸屏和威纶通触摸屏功能:实现PLC与变频器进行modbus通讯,触摸屏控制启停,设置设定频率,加减速时间读取实际频率,电压,电流。说明:程序带注释,资料全程序可以直接用于现场生产。YID:7725......
  • 一款Mac专用极具创意的绘图软件—Sketch
    Sketchmac是一款极具创意的绘图软件,它可以让您像玩游戏一样使用鼠标在屏幕上拖动来实现各种形状的效果,并创建有无数种效果。它还具有强大的绘制能力和功能,如图形、线条、网格等。该软件也是Sketch软件家族中比较独特的一款绘图软件。它不仅可以绘制文本,图像,音乐图标和文字,而且还......
  • 三菱FX3U与台达变频器通讯器件:三菱FX3U PLC+FX3U 485BD板,台达VFD变频器,昆仑通态触摸屏
    三菱FX3U与台达变频器通讯器件:三菱FX3UPLC+FX3U485BD板,台达VFD变频器,昆仑通态触摸屏功能:采用485方式,modbusRTU协议,对台达变频器频率设定,正反转,点动控制,频率,电流电压读取说明:是程序非实物,程序带有注释,触摸屏程序(昆仑通态或威纶通都可以)。ID:5425586347363279......
  • 信捷XC系列PLC与7台易能变频器 同时通讯程序 易能变频器通讯控制程序。
    信捷XC系列PLC与7台易能变频器同时通讯程序易能变频器通讯控制程序。程序有注释。可以完成7台易能变频器的通讯。器件:信捷XC3PLC,易能EDS800变频器,触摸屏是昆仑通态。采用信捷XC3的PLC,利用无协议指令,触摸屏控制,同时控制7台变频器频率设定,频率读取。已经用于客户实际生产运行中,通......