WebClient не загружает нужный файл с предоставленного URL-адреса

Я хочу загрузить файл .torrent из дистрибутива Linux, но по какой-то причине окончательный файл, загруженный из моего приложения, отличается от файла, загруженного вручную. Тот, который загружает мое приложение, имеет размер 31 КБ, и это недопустимый файл .torrent, а правильный (когда я загружаю вручную) имеет размер 41 КБ, и он действителен.

URL-адрес файла, который я хочу загрузить, следующий: http://torcache.net/torrent/C348CBCA08288AE07A97DD641C5D09EE25299FAC.torrent

Почему это происходит и как я могу скачать тот же файл (действительный, с 41 КБ)?

Спасибо.


Код C# из метода загрузки указанного выше файла:

        string sLinkTorCache = @"http://torcache.net/torrent/C348CBCA08288AE07A97DD641C5D09EE25299FAC.torrent";
        using (System.Net.WebClient wc = new System.Net.WebClient())
        {
            var path = @"D:\Baixar automaticamente"; // HACK Pegar isso dos settings na versão final
            var data = Helper.Retry(() => wc.DownloadData(sLinkTorCache), TimeSpan.FromSeconds(3), 5);
            string fileName = null;

            // Try to extract the filename from the Content-Disposition header
            if (!string.IsNullOrEmpty(wc.ResponseHeaders["Content-Disposition"]))
            {
                fileName = wc.ResponseHeaders["Content-Disposition"].Substring(wc.ResponseHeaders["Content-Disposition"].IndexOf("filename=") + 10).Replace("\"", "");
            }

            var torrentPath = Path.Combine(path, fileName ?? "Arch Linux Distro");

            if (File.Exists(torrentPath))
            {
                File.Delete(torrentPath);
            }

            Helper.Retry(() => wc.DownloadFile(new Uri(sLinkTorCache), torrentPath), TimeSpan.FromSeconds(3), 5);
        }

Helper.Retry (попробуйте выполнить метод еще раз в случае исключений HTTP):

    public static void Retry(Action action, TimeSpan retryInterval, int retryCount = 3)
    {
        Retry<object>(() =>
        {
            action();
            return null;
        }, retryInterval, retryCount);
    }

    public static T Retry<T>(Func<T> action, TimeSpan retryInterval, int retryCount = 3)
    {
        var exceptions = new List<Exception>();

        for (int retry = 0; retry < retryCount; retry++)
        {
            try
            {
                if (retry > 0)
                    System.Threading.Thread.Sleep(retryInterval); // TODO adicionar o Using pro thread
                return action();
            }
            catch (Exception ex)
            {
                exceptions.Add(ex);
            }
        }

        throw new AggregateException(exceptions);
    }

person Gabriel Duarte    schedule 26.01.2016    source источник
comment
Почему вы загружаете файл дважды в свой код? DownloadData и DownloadFile   -  person Rob    schedule 26.01.2016


Ответы (1)


Сначала я думал, что сайт отвечает мусором, если он думал, что это запрос от бота (то есть он проверял некоторые заголовки). После просмотра Fiddler оказалось, что возвращаемые данные точно такие же, как и для как веб-браузер, так и код. Это означает, что мы неправильно выкачиваем (извлекаем) ответ. Веб-серверы очень часто сжимают данные (используя что-то вроде gzip). WebClient не автоматически выкачивает данные.

Используя ответ из Автоматически распаковывать ответ gzip через WebClient.DownloadData - я удалось заставить его работать должным образом.

Также обратите внимание, что вы загружаете файл дважды. Вам не нужно этого делать.

Рабочий код:

//Taken from above linked question
class MyWebClient : WebClient
{
    protected override WebRequest GetWebRequest(Uri address)
    {
        HttpWebRequest request = base.GetWebRequest(address) as HttpWebRequest;
        request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
        return request;
    }
}

И используя его:

string sLinkTorCache = @"http://torcache.net/torrent/C348CBCA08288AE07A97DD641C5D09EE25299FAC.torrent";
using (var wc = new MyWebClient())
{
  var path = @"C:\Junk";
  var data = Helper.Retry(() => wc.DownloadData(sLinkTorCache), TimeSpan.FromSeconds(3), 5);
  string fileName = "";

  var torrentPath = Path.Combine(path, fileName ?? "Arch Linux Distro.torrent");

  if (File.Exists(torrentPath))
      File.Delete(torrentPath);

    File.WriteAllBytes(torrentPath, data);
}
person Rob    schedule 26.01.2016