C# скачать файл с резюме (Content-Range)

Есть ли у нас какая-нибудь библиотека или класс C#, которые могут загружать большой файл по частям, и если соединение не удается, возобновить загрузку?

Я попытался использовать встроенный класс WebClient, так как он не поддерживает возобновление загрузки.

WebClient webClient = new WebClient();
webClient.DownloadFile(link, @"C:\Test\1.zip");

Ошибка с исключением: "Получен неожиданный EOF или 0 байтов из транспортного потока".

2 ответа

Я сделал некоторый код, который загружает файл с поддержкой резюме.

    static bool DownloadFileWithRange()
    {
        string link = "http://freelistenonline.com/"; //<- link to some big file
        string FilePath = @"C:\Test\1.zip";

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

        long totalBytesRead = 0;
        long MaxContentLength = 0;
        long RequestContentLength = 0;
        int i = 0;
        while (MaxContentLength == 0 || totalBytesRead < MaxContentLength)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(link);

            if (totalBytesRead > 0) request.AddRange(totalBytesRead);

            WebResponse response = request.GetResponse();

            Console.WriteLine("=============== Request #{0} ==================", ++i);
            foreach (var header in response.Headers)
            {
                if (header.ToSaveString().Contains("Content-Length") || header.ToSaveString().Contains("Content-Range"))
                    Console.WriteLine("{0}: {1}", header, response.Headers[header.ToString()]);
            }

            if (response.ContentLength > MaxContentLength)
                MaxContentLength = response.ContentLength;             

            var ns = response.GetResponseStream();
            RequestContentLength = 0;
            try
            {
                using (var responseStream = response.GetResponseStream())
                {
                    using (FileStream localFileStream = new FileStream(FilePath, FileMode.Append))
                    {
                        var buffer = new byte[4096];
                        int bytesRead;

                        while ((bytesRead = responseStream.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            totalBytesRead += bytesRead;
                            RequestContentLength += bytesRead;
                            localFileStream.Write(buffer, 0, bytesRead);
                        }

                        Console.WriteLine("Got bytes: {0}", RequestContentLength);
                    }

                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Got bytes: {0}", RequestContentLength);
            }
        }

        if (MaxContentLength == totalBytesRead)
            return true;

        return false;
    }

Я понимаю, что это более старый пост, но ответ Герцога очень ценный и хотел прояснить некоторые моменты. Я часто ссылаюсь на этот пост, и это закономерности. Однако его можно возобновить лишь частично, в первых пяти строках мы отрезаем себе нос, удаляя любой предыдущий прогресс. Мы уже делаем возможным добавить диапазон к запросу, поэтому давайте прочитаем FileInfo(FilePath) для существующих файлов и сэкономим драгоценное время. Если есть подозрение на повреждение файла (например, сбой питания), вы можете даже сократить его на несколько байтов, чтобы обеспечить чистый файл.

Также использование этого условия «цикл до» может закончиться «бесконечным» кошмаром. Есть много других причин для частичной загрузки, помимо простого исключения, зафиксированного здесь. Я сталкивался с множеством моментов, когда все просто останавливается. Когда вы добавляете асинхронные шаблоны и параллелизм, неизвестные сбои продолжают появляться. Мораль состоит в том, чтобы всегда стараться "выходить" во время цикла, пока ...

      static bool DownloadFileWithRange()
{
    string link = "http://freelistenonline.com/"; //<- link to some big file
    string FilePath = @"C:\Test\1.zip";

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

    long totalBytesRead = 0;
    long MaxContentLength = 0;
    long RequestContentLength = 0;
    int i = 0;
    while (MaxContentLength == 0 || totalBytesRead < MaxContentLength)
    {
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(link);

        if (totalBytesRead > 0) request.AddRange(totalBytesRead);

        WebResponse response = request.GetResponse();

        Console.WriteLine("=============== Request #{0} =================="
Другие вопросы по тегам