Question

Je crée un programme qui télécharge des fichiers via http.

Je l’ai téléchargé, mais je veux pouvoir suspendre les téléchargements, fermer le programme et les reprendre à une date ultérieure.

Je connais l'emplacement où je les télécharge. Cela prend en charge.

Je télécharge le fichier via HttpWebResponse et lis la réponse dans un flux à l'aide de GetResponseStream.

Lorsque je ferme l'application et que je la redémarre, je ne peux plus reprendre le téléchargement. J'ai essayé d'effectuer une recherche sur le flux, mais il est indiqué que ce n'est pas pris en charge.

Quelle serait la meilleure façon de faire cela?

Était-ce utile?

La solution

Si le serveur le permet, vous devez envoyer le Range En-tête HTTP avec votre demande à l'aide de AddRange méthode:

request.AddRange(1024);

Ceci demandera au serveur de commencer à envoyer le fichier après le 1er kilo-octet. Ensuite, il suffit de lire le flux de réponses normalement.

Pour vérifier si un serveur prend en charge la reprise, vous pouvez envoyer une demande HEAD et vérifier s'il envoie l'en-tête Accept-Ranges: bytes .

Autres conseils

Qu'en est-il d'une classe HTTPRangeStream?

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;

namespace Ionic.Kewl
{
    public class HTTPRangeStream : Stream
    {
        private string url;
        private long length;
        private long position;
        private long totalBytesRead;
        private int totalReads;

        public HTTPRangeStream(string URL)
        {
            url = URL;
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
            HttpWebResponse result = (HttpWebResponse)request.GetResponse();
            length = result.ContentLength;
        }

        public long TotalBytesRead    { get { return totalBytesRead; } }
        public long TotalReads        { get { return totalReads; } }
        public override bool CanRead  { get { return true; } }
        public override bool CanSeek  { get { return true; } }
        public override bool CanWrite { get { return false; } }
        public override long Length   { get { return length; } }

        public override bool CanTimeout
        {
            get
            {
                return base.CanTimeout;
            }
        }


        public override long Position
        {
            get
            {
                return position;
            }
            set
            {
                if (value < 0) throw new ArgumentException();
                position = value;
            }
        }

        public override long Seek(long offset, SeekOrigin origin)
        {
            switch (origin)
            {
                case SeekOrigin.Begin:
                    position = offset;
                    break;
                case SeekOrigin.Current:
                    position += offset;
                    break;
                case SeekOrigin.End:
                    position = Length + offset;
                    break;
                default:
                    break;
            }
            return Position;
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
            request.AddRange(Convert.ToInt32(position), Convert.ToInt32(position) + count);
            HttpWebResponse result = (HttpWebResponse)request.GetResponse();
            using (Stream stream = result.GetResponseStream())
            {
                stream.Read(buffer, offset, count);
                stream.Close();
            }
            totalBytesRead += count;
            totalReads++;
            Position += count;
            return count;
        }


        public override void Write(byte[] buffer, int offset, int count)
        {
            throw new NotSupportedException();
        }

        public override void SetLength(long value)
        {
            throw new NotSupportedException();
        }
        public override void Flush()
        {
            throw new NotSupportedException();
        }

    }
}

Votre solution est correcte, mais elle ne fonctionnera que dans les cas où le serveur envoie un en-tête Content-Length. Cet en-tête ne sera pas présent dans le contenu généré dynamiquement.

Cette solution consiste également à envoyer une demande pour chaque lecture. Si le contenu change sur le serveur entre les demandes, vous obtiendrez des résultats incohérents.

J'améliorerais cela en stockant les données localement, sur disque ou en mémoire. Ensuite, vous pouvez y chercher tout ce que vous voulez. Il n’y aura pas de problème d’incohérence et vous aurez besoin d’un seul HttpWebRequest pour le télécharger.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top