简体   繁体   English

使用webclient DownloadFileAsync多个文件

[英]DownloadFileAsync multiple files using webclient

Description 描述
Download multiple files using webclient's DownloadFileAsync and utilizing a text file for URL input for download. 使用webclient的DownloadFileAsync下载多个文件,并使用文本文件进行URL输入下载。

Problem 问题
The approach that I have used won't download files at all. 我使用的方法根本不会下载文件。 Just runs and does nothing. 只是跑步而且什么都不做。 It fills the list array then quits the program without downloading a single file. 它填充列表数组然后退出程序而不下载单个文件。 I have googled for solutions but come up shorthanded. 我已经google了解决方案,但缺乏信心。 Then attempted to search for a solution in the database here with same results. 然后尝试在此处搜索数据库中的解决方案,结果相同。 Any help is appreciated. 任何帮助表示赞赏。

Questions 问题

  1. Why does this approach not work? 为什么这种方法不起作用?
  2. What can I do to improve this and learn from this. 我该怎么做才能改善这一点并从中吸取教训。

Code
DownloadClass.cs DownloadClass.cs

using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Net;
using System.Threading;
using System.Windows.Forms;

namespace ThreadTest
{
    class DownloadClass
    {
        public struct download
        {
            public static string URL { get; set; }
            public static string file { get; set; }
            public static string[] link;
            public static int downloadcount;
        }

        public static List<string> list = new List<string>();
        public static WebClient wc = new WebClient();

        public static void Download()
        {
            int count = 0;
            download.URL = list[0];
            Uri URI = new Uri(download.URL);
            UriBuilder uri = new UriBuilder(URI);
            download.link = uri.Path.ToLower().Split(new char[] { '/' });

            count = 0;
            // Find file
            foreach (string abs in download.link)
            {
                count++;
                if (abs.ToLower().Contains(".html") || abs.ToLower().Contains(".exe") || abs.ToLower().Contains(".txt"))
                {
                    try
                    {
                        download.file = download.link[count];
                        wc.Proxy = null;
                        wc.DownloadFileCompleted += new AsyncCompletedEventHandler(wc_DownloadFileCompleted);
                        wc.DownloadFileAsync(URI, Application.StartupPath + "\\" + download.file);
                        break;
                    }
                    catch (Exception)
                    { }
                }
            }
        }

        public static void BeginDownload()
        {
            new Thread(Download).Start();
        }

        public static void wc_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
        {
            int count = 0;
            download.downloadcount++;
            download.URL = list[0];
            Uri URI = new Uri(download.URL);
            UriBuilder uri = new UriBuilder(URI);

            download.link = uri.Path.ToLower().Split(new char[] { '/' });

            count = 0;
            // Find file
            foreach (string abs in download.link)
            {
                count++;
                if (abs.ToLower().Contains(".html") || abs.ToLower().Contains(".exe") || abs.ToLower().Contains(".txt"))
                {
                    try
                    {
                        download.file = download.link[count];
                    }
                    catch (Exception)
                    { }
                }
            }
            list.RemoveAt(0);
            if (list.Count > 0)
            {
                wc.DownloadFileAsync(URI, list[download.downloadcount], Application.StartupPath + "\\" + download.file);
            }
            else
            {
                Console.WriteLine("Downloading is done.");
                Environment.Exit(0);
            }
        }
    }
}

Program.cs (Main Class) Program.cs(主类)

using System;
using System.IO;
using System.Collections.Generic;
using System.Windows.Forms;

namespace ThreadTest
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length < 1)
            {
                Console.WriteLine("Usage: {0} <download txtfile>", Environment.GetCommandLineArgs()[0]);
                Environment.Exit(0);
            }

            int counter = 0;
            string line;
            string format = string.Format("{0}\\{1}", Application.StartupPath, args[0]);

            // Read the file line by line.
            using(StreamReader file = new StreamReader(format))
            {
                while ((line = file.ReadLine())!= null)
                {
                    // Store urls in a list.
                    DownloadClass.list.Add(line);
                    counter++;
                }
            }
            DownloadClass.BeginDownload();
        }
    }
}

Besides being bad design there are lots of issues that lead to your code not (or nor correctly working). 除了糟糕的设计之外,还有许多问题会导致您的代码无法(或者无法正常工作)。

  1. You need to make sure that you application lives while it downloads something. 您需要确保应用程序在下载内容时存在。 Your current app quits right away (you have to wait for the downloading to complete in your main). 您当前的应用程序立即退出(您必须等待主要内容的下载完成)。
  2. You application may download the same file multiple times but not download others at all (You need to completely lock object when they are used in an async=multithreading way like here when accessing static objects) BTW: Don't use static objects at all to avoid that in the first place. 您的应用程序可能会多次下载相同的文件,但根本不会下载其他文件(当访问静态对象时,您需要完全锁定对象,如同这里的async =多线程一样)BTW:根本不要使用静态对象首先要避免这种情况。
  3. Even if 2 is corrected it may still download the same file multiple times into the same filename and thus fail. 即使2被更正,它仍然可以将相同的文件多次下载到相同的文件名中,从而失败。

As long as you have no knowledge about multithreading I'd recommend you use the synchoneous methods to avoid all those problems. 只要您不了解多线程,我建议您使用同步方法来避免所有这些问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM