如何在C#中以编程方式下载大文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2269607/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-07 00:55:17  来源:igfitidea点击:

How to programmatically download a large file in C#

c#webclientdownloadlarge-files

提问by hIpPy

I need to programmatically download a large file before processing it. What's the best way to do that? As the file is large, I want to specific time to wait so that I can forcefully exit.

我需要在处理之前以编程方式下载一个大文件。这样做的最佳方法是什么?由于文件很大,我想在特定的时间等待,以便我可以强制退出。

I know of WebClient.DownloadFile(). But there does not seem a way to specific an amount of time to wait so as to forcefully exit.

我知道 WebClient.DownloadFile()。但是似乎没有办法指定等待的时间以强制退出。

try
{
    WebClient client = new WebClient();
    Uri uri = new Uri(inputFileUrl);
    client.DownloadFile(uri, outputFile);
}
catch (Exception ex)
{
    throw;
}

Another way is to use a command line utility (wget) to download the file and fire the command using ProcessStartInfo and use Process' WaitForExit(int ms) to forcefully exit.

另一种方法是使用命令行实用程序 (wget) 下载文件并使用 ProcessStartInfo 触发命令,并使用 Process' WaitForExit(int ms) 强制退出。

ProcessStartInfo startInfo = new ProcessStartInfo();
//set startInfo object

try
{
    using (Process exeProcess = Process.Start(startInfo))
    {
        //wait for time specified
        exeProcess.WaitForExit(1000 * 60 * 60);//wait till 1m

        //check if process has exited
        if (!exeProcess.HasExited)
        {
            //kill process and throw ex
            exeProcess.Kill();
            throw new ApplicationException("Downloading timed out");
        }
    }
}
catch (Exception ex)
{
    throw;
}

Is there a better way? Please help. Thanks.

有没有更好的办法?请帮忙。谢谢。

采纳答案by Remus Rusanu

Use a WebRequestand get the response stream. Then read from the reponse Stream blocks of bytes, and write each block to the destination file. This way you can control when to stop if the download takes too long, as you get control between chunks and you can decide if the download has timed out based on a clock:       

使用WebRequest并获取响应流。然后从响应 Stream 中读取字节块,并将每个块写入目标文件。通过这种方式,您可以控制在下载时间过长的情况下何时停止,因为您可以在块之间进行控制,并且您可以根据时钟确定下载是否超时:       

        DateTime startTime = DateTime.UtcNow;
        WebRequest request = WebRequest.Create("http://www.example.com/largefile");
        WebResponse response = request.GetResponse();
        using (Stream responseStream = response.GetResponseStream()) {
            using (Stream fileStream = File.OpenWrite(@"c:\temp\largefile")) { 
                byte[] buffer = new byte[4096];
                int bytesRead = responseStream.Read(buffer, 0, 4096);
                while (bytesRead > 0) {       
                    fileStream.Write(buffer, 0, bytesRead);
                    DateTime nowTime = DateTime.UtcNow;
                    if ((nowTime - startTime).TotalMinutes > 5) {
                        throw new ApplicationException(
                            "Download timed out");
                    }
                    bytesRead = responseStream.Read(buffer, 0, 4096);
                }
            }
        }

回答by BFree

How about using DownloadFileAsyncin the WebClient class. The cool thing about going this route is that you can cancel the operation by calling CancelAsyncif it takes too long. Basically, call this method, and if a specified amount of time elapses, call Cancel.

DownloadFileAsync在 WebClient 类中使用如何。走这条路线很酷的一点是,CancelAsync如果时间太长,您可以通过调用取消操作。基本上,调用此方法,如果经过指定的时间量,则调用 Cancel。

回答by orip

Asked here: C#: Downloading a URL with timeout

在这里提问:C#:下载带有超时的 URL

Simplest solution:

最简单的解决方案:

public string GetRequest(Uri uri, int timeoutMilliseconds)
{
    var request = System.Net.WebRequest.Create(uri);
    request.Timeout = timeoutMilliseconds;
    using (var response = request.GetResponse())
    using (var stream = response.GetResponseStream())
    using (var reader = new System.IO.StreamReader(stream))
    {
        return reader.ReadToEnd();
    }
}

Better (more flexible) solution is this answerto the same question, in the form of a WebClientWithTimeouthelper class.

更好(更灵活)的解决方案是以辅助类的形式回答同一问题WebClientWithTimeout

回答by Daniel Caballero

You can use DownloadFileAsyncas @BFree said and then try with the following WebClient's events

您可以DownloadFileAsync像@BFree 所说的那样使用,然后尝试使用以下 WebClient 的事件

protected virtual void OnDownloadProgressChanged(DownloadProgressChangedEventArgs e);
protected virtual void OnDownloadFileCompleted(AsyncCompletedEventArgs e);

Then you can know the Progress Percentage

然后你就可以知道进度百分比

e.ProgressPercentage

Hope this helps

希望这可以帮助