【问题标题】:WebClient.OpenRead download data in chunksWebClient.OpenRead 分块下载数据
【发布时间】:2011-09-14 23:16:47
【问题描述】:

我正在尝试使用 Webclient 对象以每个 5% 的块下载数据。原因是我需要报告每个下载块的进度。

这是我为完成这项任务而编写的代码:

    private void ManageDownloadingByExtractingContentDisposition(WebClient client, Uri uri)
    {
        //Initialize the downloading stream 
        Stream str = client.OpenRead(uri.PathAndQuery);

        WebHeaderCollection whc = client.ResponseHeaders;
        string contentDisposition = whc["Content-Disposition"];
        string contentLength = whc["Content-Length"];
        string fileName = contentDisposition.Substring(contentDisposition.IndexOf("=") +1);

        int totalLength = (Int32.Parse(contentLength));
        int fivePercent = ((totalLength)/10)/2;

        //buffer of 5% of stream
        byte[] fivePercentBuffer = new byte[fivePercent];

        using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite))
        {
            int count;
            //read chunks of 5% and write them to file
            while((count = str.Read(fivePercentBuffer, 0, fivePercent)) > 0);
            {
                fs.Write(fivePercentBuffer, 0, count);
            }
        }
        str.Close();
    }

问题 - 当它到达 str.Read() 时,它会暂停读取整个流,然后计数为 0。所以 while() 不起作用,即使我指定只读为与五百分比变量一样多。看起来它在第一次尝试时读取了整个流。

我怎样才能让它正确读取块?

谢谢,

安德烈

【问题讨论】:

  • 注册 WebClient.DownloadProgressChanged 事件,然后调用 WebClient.DownloadDataAsync()。您可以在事件回调中更新您的进度。

标签: c# stream webclient chunks


【解决方案1】:

while 循环的行尾有一个分号。我很困惑为什么接受的答案是正确的,直到我注意到这一点。

【讨论】:

    【解决方案2】:
    do
    {
        count = str.Read(fivePercentBuffer, 0, fivePercent);
        fs.Write(fivePercentBuffer, 0, count);
    } while (count > 0);
    

    【讨论】:

    • 这行得通,谢谢。无法弄清楚为什么它会起作用。可能是因为 while 是在 count 被修改之后。
    【解决方案3】:

    如果您不需要精确的 5% 块大小,您可能需要研究异步下载​​方法,例如 DownloadDataAsyncOpenReadAsync

    每次下载新数据并且进度发生变化时,它们都会触发 DownloadProgressChanged 事件,并且事件会在事件 args 中提供完成百分比。

    一些示例代码:

    WebClient client = new WebClient();
    Uri uri = new Uri(address);
    
    // Specify a progress notification handler.
    client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(DownloadProgressCallback);
    
    client.DownloadDataAsync(uri);
    
    static void DownloadProgressCallback(object sender, DownloadProgressChangedEventArgs e)
    {
        // Displays the operation identifier, and the transfer progress.
        Console.WriteLine("{0}    downloaded {1} of {2} bytes. {3} % complete...", 
            (string)e.UserState, 
            e.BytesReceived, 
            e.TotalBytesToReceive,
            e.ProgressPercentage);
    }
    

    【讨论】:

    • 感谢您的建议,但该应用程序不允许异步下载。我必须找到一种处理同步下载进度报告的方法。
    • 您能否澄清“应用程序不允许异步下载”的含义?您的应用程序如何防止这种情况发生?
    • 我的应用程序需要下载多个文件,并且需要同步下载它们,一次一个,这只是对任务的请求。最初,我使用的是同步下载的 webclient.DownloadFile(),但我还需要报告进度,所以我想到了使用 webClient.OpenRead() 来报告块。
    • @Andrei 您可以尝试链接下载请求。下载一个文件,然后在下载完成后,为事件处理程序中的下一个文件调用 DownloadDataAsync。
    • 虽然我同意你的观点,并且理解你的意思,我同意这是最明显和最简单的解决方案,但我正在处理的应用程序处于如此高级的水平,以至于切换到异步下载将需要一段客户完全无法接受的开发和重新测试时间。所以这就是为什么我希望我发布的代码中有一些错误可以使它起作用。
    猜你喜欢
    • 1970-01-01
    • 2012-08-23
    • 1970-01-01
    • 2014-08-15
    • 1970-01-01
    • 1970-01-01
    • 2021-07-24
    • 2013-01-14
    • 1970-01-01
    相关资源
    最近更新 更多