【问题标题】:WebClient is not following redirects in .Net Core 3.1WebClient 未遵循 .Net Core 3.1 中的重定向
【发布时间】:2020-11-29 07:08:55
【问题描述】:

我尝试下载带有返回 307 重定向代码的 URL 的文件。

我尝试使用WebClient.DownloadFile 方法,但它似乎没有遵循所请求站点的重定向。我通过搜索这个问题找到的东西要么说它应该可以工作(微软文档),要么没有真正回答我的问题:WebClient Does not automatically redirect

我的第一个问题是为什么它不遵循重定向,即使它使用的 HttpWebRequest 有AllowAutoRedirect=true

我的第二个问题是如何最好地实现一个下载具有自动重定向的文件的功能。

我使用的示例 URL 是:https://api.spiget.org/v2/resources/10905/download
但是这个 URL 并不总是重定向,这取决于我猜的一些内部 API 状态。

【问题讨论】:

  • WebClient 是过时的 API,尝试使用 HttpClient
  • 您需要进度报告吗?停止/恢复下载?您正在开发什么样的应用程序?
  • 好的,HttpClient 正在工作,我现在使用它,但进度报告将是一个不错的功能。

标签: c# .net-core-3.1


【解决方案1】:

这是一个简单的例子,HttpClient

.NET Core 3.1 控制台应用(UPD: 添加进度报告)

class Program
{
    private static readonly HttpClient client = new HttpClient(new HttpClientHandler() { AllowAutoRedirect = true });

    static async Task Main(string[] args)
    {
        try
        {
            IProgress<int> progress = new Progress<int>(p => 
            {
                Console.Write(p + " ");
            });
            await DownloadAndSaveFileAsync("https://api.spiget.org/v2/resources/10905/download", progress);
            Console.WriteLine();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        Console.WriteLine("Done.");
        Console.ReadKey();
    }

    private static async Task DownloadAndSaveFileAsync(string url, IProgress<int> progress)
    {
        using HttpResponseMessage response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);
        response.EnsureSuccessStatusCode(); // throw if not success
        string fileName = response.Content.Headers.ContentDisposition?.FileName ?? throw new Exception("Nothing to download");
        fileName = fileName.Trim('\"'); // remove quotes
        long contentLength = response.Content.Headers.ContentLength ?? 0;

        Console.WriteLine("File: {0}", fileName);
        Console.WriteLine("Content-Length: {0} bytes", contentLength);

        using Stream responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
        using FileStream fileStream = File.Create(fileName);

        int bufferSize = 65536;
        byte[] buffer = new byte[bufferSize];
        int bytesRead;
        long position = 0;
        int storedPercentage = -1;
        while ((bytesRead = await responseStream.ReadAsync(buffer, 0, bufferSize)) > 0)
        {
            await fileStream.WriteAsync(buffer, 0, bufferSize);
            if (contentLength > 0)
            {
                position += bytesRead;
                int percentage = (int)(position * 100 / contentLength);
                if (percentage != storedPercentage)
                {
                    progress?.Report(percentage);
                    storedPercentage = percentage;
                }
            }
        }
    }
}

控制台输出

File: [1.8 TO 1.16] Ultra Cosmetics [OPENSOURCE & FREE!!]#10905.jar
Content-Length: 1692542 bytes
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 73 72 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
Done.

文件下载成功。

与在浏览器中下载的逐字节比较。文件是相同的。

【讨论】:

  • 非常感谢!这是我问题的完美答案。类似于 WebClient 的 API 在 .NET 5 中会很棒
猜你喜欢
  • 1970-01-01
  • 2020-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-01
  • 2013-09-11
相关资源
最近更新 更多