Télécharger le fichier progressivement en utilisant TIdHttp
Je veux implémenter un simple http downloader aide TIdHttp (Indy10). J'ai trouvé deux exemples de code à partir de l'internet. Malheureusement aucun d'eux ne me satisfait à 100%. Voici le code et je veux quelques conseils.
Variante 1
var
Buffer: TFileStream;
HttpClient: TIdHttp;
begin
Buffer := TFileStream.Create('somefile.exe', fmCreate or fmShareDenyWrite);
try
HttpClient := TIdHttp.Create(nil);
try
HttpClient.Get('http://somewhere.com/somefile.exe', Buffer); // wait until it is done
finally
HttpClient.Free;
end;
finally
Buffer.Free;
end;
end;
Le code est compact et très facile à comprendre. Le problème est qu'il alloue de l'espace disque lorsque le téléchargement commence. Un autre problème est que nous ne pouvons pas afficher la progression du téléchargement dans l'interface utilisateur directement, sauf si le code est exécuté dans un thread d'arrière-plan (sinon, nous pouvons lier HttpClient.OnWork événement).
Variante 2:
const
RECV_BUFFER_SIZE = 32768;
var
HttpClient: TIdHttp;
FileSize: Int64;
Buffer: TMemoryStream;
begin
HttpClient := TIdHttp.Create(nil);
try
HttpClient.Head('http://somewhere.com/somefile.exe');
FileSize := HttpClient.Response.ContentLength;
Buffer := TMemoryStream.Create;
try
while Buffer.Size < FileSize do
begin
HttpClient.Request.ContentRangeStart := Buffer.Size;
if Buffer.Size + RECV_BUFFER_SIZE < FileSize then
HttpClient.Request.ContentRangeEnd := Buffer.Size + RECV_BUFFER_SIZE - 1
else
HttpClient.Request.ContentRangeEnd := FileSize;
HttpClient.Get(HttpClient.URL.URI, Buffer); // wait until it is done
Buffer.SaveToFile('somefile.exe');
end;
finally
Buffer.Free;
end;
finally
HttpClient.Free;
end;
end;
Nous avons d'abord interroger la taille de fichier du serveur, puis nous télécharger le contenu du fichier en morceaux. (Extrait le contenu du fichier sera enregistré sur le disque lorsqu'ils sont reçus correctement. Le problème potentiel est que nous avons à envoyer plusieurs demandes pour le serveur. Je ne sais pas si certains serveurs (megaupload) peut limiter le nombre de demandes dans un délai de période de temps donnée.
Mes attentes
- L'utilisateur doit envoyer un seul GET-demande au serveur.
- L'espace disque ne doit pas être attribuée lorsque le téléchargement commence.
Tous les conseils sont appréciés.
- Si vous voulez une mise en cache
TFileStream
, regardez David contribution ici: Tampon fichiers (pour les accès disque plus rapide).
Vous devez vous connecter pour publier un commentaire.
Variante #1 est la plus simple, et est comment Indy est destiné à être utilisé.
Concernant l'allocation de l'espace disque, vous pouvez dériver une nouvelle classe de
TFileStream
et de remplacer sonSetSize()
méthode pour ne rien faire.TIdHTTP
va encore tenter de pré-allouer le fichier lorsque cela est approprié, mais il ne sera pas réellement allouer de l'espace disque. Écrit àTFileStream
augmentera le fichier en tant que de besoin.Concernant les rapports d'état,
TIdHTTP
aOnWork...
événements à cette fin. LeAWorkCountMax
paramètre de laOnWorkBegin
sera la taille réelle du fichier si elle est connue (la réponse n'est pas mémorisé en bloc), ou 0 si pas connue. LeAWorkCount
paramètre de laOnWork
événement sera le nombre total d'octets qui ont été transférés jusqu'à présent. Si la taille du fichier est connu, vous pouvez afficher le pourcentage total en divisant simplement leAWorkCount
par leAWorkCountMax
et en multipliant le résultat par 100, sinon il suffit d'afficher leAWorkCount
valeur par lui-même. Si vous souhaitez afficher la vitesse de transfert, vous pouvez calculer que de la différence deAWorkCount
valeurs et les intervalles de temps entre plusieursOnWork
événements.Essayez ceci:
.
TDateTime
parce que je ne voulais pas le code affecté par d'éventuelles modifications de l'horloge (heure d'été, manipulation,etc). En outre, le code est le moment les intervalles entre les événements, qui ne viendra jamais à proximité de la 49.7 jour limite deLongWord
.GetTickDiff()
comptes pour le wrap-around qui se produit chaque foisGetTickCount()
revient à zéro, de sorte que n'est pas un problème.Voici un exemple qui montre comment utiliser les composants OnWork pour afficher une barre de progression:
Télécharger un Fichier à partir d'internet par programmation avec une Progression de l'événement à l'aide de Delphi et Indy
Vous ne devriez pas vous inquiéter au sujet de l'allocation de l'espace disque. L'espace disque qui vous est alloué n'est pas écrit, donc il ne sera pas endommager vos disques. Être heureux qu'il est affecté de sorte qu'il n'est pas possible qu'un autre processus de revendications de l'espace disque et laissez vous manquez d'espace!
N'oubliez pas d'ajouter ce pour la Variante 2
Remplacer
Par