zwyx
Messages postés146Date d'inscriptionjeudi 22 novembre 2007StatutMembreDernière intervention21 mars 2016
-
18 févr. 2008 à 12:16
cs_arghhh
Messages postés1Date d'inscriptionlundi 7 avril 2008StatutMembreDernière intervention22 septembre 2008
-
22 sept. 2008 à 14:43
Bonjour à tous,
Je souhaite réaliser une petite interface qui enregistre toutes les images jpeg d'un site, mais ça pourrait très bien être un autre type de fichiers que des images. Je m'explique plus en détail.
L'utilisateur inscrit dans plusieurs TEdit, de manière à ce que l'on ait:
edtSource1.Text := 'http://www.sitequelconque.com/images/image_';
edtSourceFirst.Text := '1';
edtSourceLast.Text := '250';
edtSource2.Text := '.jpg';
Le programme se charge ensuite d'enregistrer les 250 images dans un dossier choisi à l'aide d'un ShellTreeView (ce n'est pas cette partie qui pose problème):
http.//www.sitequelconque.com/images/image_1.jpg
http.//www.sitequelconque.com/images/image_2.jpg
...
http.//www.sitequelconque.com/images/image_250.jpg
Dans un premier temps, je pensais pouvoir faire abstraction du format des fichiers à enregistrer, car je pensais pouvoir faire qu'une simple copie octet par octet. Mais ne sachant pas trop comment m'y prendre, j'ai essayé d'ouvrir une image à partir de son URL, dans un TMemoryStream. Je bloque déjà sur cette simple opération en ayant écrit les quelques lignes suivantes.
procedure TForm1.btnSaveClick(Sender: TObject);
var
memviv: TMemoryStream;
adr: ShortString;
ch: ShortString;
begin
adr := 'http://www.chu-nantes.fr/02-SiteWeb/02-Index/LogoCHU(627_27)122x82.jpg';
ch := 'C:\Documents and Settings\MaSession\Bureau\';
memviv.Create;
memviv.LoadFromFile(adr); // provoque l'erreur à l'exécution: "impossible d'ouvrir le fichier ..."
memviv.SaveToFile(ch);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
adr: String;
ch : TFileName;
begin
adr:= 'http://www.chu-nantes.fr/02-SiteWeb/02-Index/LogoCHU(627_27)122x82.jpg';
ch := 'ImageDL.jpg';
if URLDownloadToFile(nil,pchar(adr), pchar(ch),0, nil)=0
then ShowMessage('Image téléchargée dans le répertore de l''application.')
else ShowMessage('Echec');
end;
zwyx
Messages postés146Date d'inscriptionjeudi 22 novembre 2007StatutMembreDernière intervention21 mars 2016 18 févr. 2008 à 15:46
Ca marche, merci beaucoup !
Je mets réponse acceptée à fbalien, car c'est le premier à m'avoir indiqué la fonction à utiliser. Avouez que je ne pouvais pas la trouver tout seul. La preuve, c'est que j'avais cherché.
Je mets également réponse acceptée à Caribensila, pour m'avoir corrigé une erreur. Le nom du fichier destinataire doit effectivement être déclaré en TFileName, et non en String. Sur ce point, j'aurais pu être plus attentif.
Et je mets finalement réponse acceptée à cirec, pour ne pas qu'il y ait de jaloux.
Je ne pense pas que ça vaille la peine de déposer mon source sur le site, une fois fini. Même si ce programme sera bien pratique (pour moi), il faut presque autant de temps pour le télécharger que pour l'écrire.
Bonne fin de journée, et encore merci.
Vous n’avez pas trouvé la réponse que vous recherchez ?
Cirec
Messages postés3833Date d'inscriptionvendredi 23 juillet 2004StatutModérateurDernière intervention18 septembre 202250 18 févr. 2008 à 16:18
"Je mets également réponse acceptée à Caribensila, pour m'avoir corrigé une erreur. Le nom du fichier destinataire doit effectivement être déclaré en TFileName, et non en String. Sur ce point, j'aurais pu être plus attentif. "
Je ne suis pas d'accord avec ça !!!
j'ai moi même utilisé plusieurs fois cette méthode et ça a toujours fonctionné avec le Type String ... le tout est de penser à le "transtyper" en PChar
Tiré des sources de Delphi :
{ Generic filename type }
TFileName = type string ;
Donc TFileName == String
" Et je mets finalement réponse acceptée à cirec, pour ne pas qu'il y ait de jaloux. "
Caribensila
Messages postés2527Date d'inscriptionjeudi 15 janvier 2004StatutMembreDernière intervention16 octobre 201918 18 févr. 2008 à 16:51
@Cirec
« Merci de ménager la susceptibilité des membres »
Surtout qu'il y a de grands sensibles, sur ce site...
Et je suis entièrement d'accord avec toi, Cirec.
On peut même utiliser le fait que TFileName ne soit "que" une String :
procedure TForm1.Button1Click(Sender: TObject);
var S : String;
begin
S := 'Mourir. La belle affaire!';
Memo1.Lines.Add(S);
Memo1.Lines.Add(ChangeFileExt(S,'... Mais vieillir!'));
end;
zwyx
Messages postés146Date d'inscriptionjeudi 22 novembre 2007StatutMembreDernière intervention21 mars 2016 18 févr. 2008 à 21:55
vos commentaires.
Bon, mon ridicule programme fonctionne correctement, mais par contre les performances sont pitoyables. Au fur et à mesure que les fichiers (j'ai essayé avec des images) s'enregistrent, cela met de plus en plus de temps, jusqu'à ce qu'on se dise que ça aurait été plus vite de les enregistrer manuellement avec iexplore.
Alors d'après ma faible expérience, soit des objets alloués dynamiquement ne sont pas détruits au fur et à meure, ce qui remplit la mémoire vive. Soit c'est parce que je n'ai pas utilisé de thread, mais vu que je ne connais rien la dessus, c'est pas gagné.
Je copie à la suite l'essentiel du code, si vous avez le courage d'y jeter un oeil.
zwyx
Messages postés146Date d'inscriptionjeudi 22 novembre 2007StatutMembreDernière intervention21 mars 2016 18 févr. 2008 à 22:10
// chaque adresse est composée de deux chaînes de caractères que l'on va concaténer, en insérant au milieu l'indice qui varie
procedure TForm1.SaveClick(Sender: TObject);
var
SourceStart, SourceEnd: String; // adresse des fichiers à enregistrer
DestinationPath: String; // répertoire dans lequel les fichiers seront enregistrés
DestinationStart, DestinationEnd: String; // nom du fichier créé par l'enregistrement
DestinationFile: TFileName; // nom du fichier créé par l'enregistrement
FileCount: Word; // compteur de boucle sur les fichiers à enregistrer
begin
// initialisation SourceStart := edtSourceStart.Text; // 'http://www.sitequelconque.com/images/image_'
SourceEnd := edtSourceEnd.Text;// '.jpg'
DestinationStart := edtDestinationStart.Text;// 'mon_image_'
DestinationEnd := edtDestinationEnd.Text; // '.jpg'
DestinationPath := stvExplorer.Path+'\'; // stvExplorer de type Shell Tree View
// boucle sur les fichiers
for FileCount : = StrToInt(edtSourceFirst.Text) to StrToInt(edtSourceLast.Text) do
begin
DestinationFile := DestinationStart+IntToStr(FileCount)+DestinationEnd; // 'mon_image_k.jpg'
URLDownloadToFile(nil, PChar(SourceStart+IntToStr(FileCount)+SourceEnd), PChar(DestinationPath+DestinationFile), 0, nil);
end;
// libération mémoire allouée pour les objets dynamiques Finalize(SourceStart);
Finalize(SourceEnd);
Finalize(DestinationPath);
Finalize(DestinationStart);
Finalize(DestinationEnd);
end; // procedure
cs_arghhh
Messages postés1Date d'inscriptionlundi 7 avril 2008StatutMembreDernière intervention22 septembre 2008 22 sept. 2008 à 14:43
Désolé pour le vide patent de mon message précédent. Je tente de réitérer:
Je pense que le problème provient d'une accumulation de demandes de download non terminées et saturant le système. De nombreux sites sont incapables de suivre la vitesse d'une boucle for.. do. Je propose d'utiliser un drapeau pour surveiller la fin d'un download AVANT de lancer le suivant (avec OnDownloadComplete).
En gros:
for ... do begin
Occupe := true;
URLDownloadToFile...
While Occupe do Application.ProcessMessages;
end;
avec:
procedure TForm1.WebBrowser1DownloadComplete(Sender: TObject);
begin
Occupe := false;
end;