0

我正在编写一个管理游戏模组/插件库的应用程序。每隔一段时间,这些 mod 中的一个都有可用的更新,并且使用 WebClient.DownloadFileAsync() 下载新版本,通过读取 WebRequest 响应中的 Content-Disposition 检索文件名。

当有两个或更多更新可用时,第一个下载非常好,但是当您尝试下载第二个文件而不重新启动应用程序时,WebClient 冻结,该文件是使用检索到的名称创建的,但包含 0 个字节,并且没有 DownloadProgressChanged 或 DownloadFileCompleted 事件被触发。

如果我不尝试检索原始文件名,而只是在本地为它们命名,那么 WebClient 不会冻结。但我需要原始文件名。

我可以做些什么来避免这个问题,同时仍然能够检索原始文件名?

private void Download(string url, string downloadDirectory)
{
    WebClient wc = new WebClient();
    string filename = FilenameFromURL(url);

    wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(DownloadProgress);
    wc.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadComplete);

    wc.DownloadFileAsync(new Uri(url), downloadDirectory + filename);
}

private string FilenameFromURL(string url)
{
    return new ContentDisposition(WebRequest.Create(url).GetResponse().Headers["Content-Disposition"].ToString()).FileName;
}

private void DownloadProgress(object sender, DownloadProgressChangedEventArgs e)
{
    downloadProgressBar.Value = e.ProgressPercentage;
}

private void DownloadComplete(object sender, AsyncCompletedEventArgs e)
{
    // ...
}
4

3 回答 3

1

我有同样的问题。经过几个小时和几个小时后,我发现问题出在未处理的流中。我用它来检查 web 目录中是否存在文件。

    private bool WebFileExists(string url)
    {
        bool exists = true;

        try
        {
            using (WebClient testClient = new WebClient())
            {
                testClient.Credentials = new NetworkCredential(_userName, _password);
                Stream stream = testClient.OpenRead(url);
                stream.Dispose();
            }
        }
        catch
        {
            exists = false;
        }

        return exists;
    }
于 2016-03-01T09:43:58.550 回答
0

实际上,我复制了您在 WPF 客户端中的相同代码。我从第一个文件中重现了这个问题。我发现在本地创建了一个 0 字节长度的文件,但没有内容。

在我的情况下,我添加的解决方案是设置用户凭据,之后我能够下载多个文件,并且重复(踩到以前的下载)。

我添加了这一行:wc.Credentials = CredentialCache.DefaultCredentials;

private void Download(string url, string downloadDirectory, string fileName)
{
    WebClient wc = new WebClient();
    wc.Credentials = CredentialCache.DefaultCredentials;

    wc.DownloadProgressChanged += DownloadProgress;
    wc.DownloadFileCompleted += DownloadComplete;
    wc.DownloadFileAsync(new Uri(url), downloadDirectory + fileName);
}
于 2013-05-26T04:03:22.123 回答
0

我设法通过通过 EventHandler 的参数传递正在下载文件的 WebClient 实例,然后使用它来获取原始文件名,而不是使用它的单独实例来检索文件名,从而解决了这个问题。

感谢这个问题帮助我找出解决方案。

使用此解决方案,因为直到文件下载后才能找到原始文件名,所以我为下载分配了一个临时名称,并在下载完成时在 AsyncCompletedEventHandler 中重命名它。

private void Download(string url, string downloadDirectory)
{
    WebClient wc = new WebClient();

    wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(DownloadProgress);
    wc.DownloadFileCompleted += new AsyncCompletedEventHandler((sender, e) => DownloadComplete(sender, e, wc));

    wc.DownloadFileAsync(new Uri(url), downloadDirectory + "temp");
}

private void DownloadProgress(object sender, DownloadProgressChangedEventArgs e)
{
    downloadProgressBar.Value = e.ProgressPercentage;
}

private void DownloadComplete(object sender, AsyncCompletedEventArgs e, WebClient wc)
{
    string filename = new ContentDisposition(wc.ResponseHeaders["Content-Disposition"].ToString()).FileName;
    if (File.Exists(downloadDirectory + "temp"))
    {
        if (File.Exists(downloadDirectory + filename))
            File.Delete(downloadDirectory + filename);
        File.Move(downloadDirectory + "temp", downloadDirectory + filename);
    }

    // ...
}
于 2013-05-27T08:09:33.027 回答