IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Composants VCL Delphi Discussion :

Indy ReadStream / WriteStream et progression


Sujet :

Composants VCL Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de souch
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    145
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juin 2003
    Messages : 145
    Par défaut Indy ReadStream / WriteStream et progression
    @ tous

    voila, je cherche toujours a paufinner une fonction de transfert de fichier qui me pose bien des soucis, et le je pense tout changer pour utiliser les fonction ReadStream et WriteStream d'indy entre un IdTcpCLient et un IdTcpServer.


    Pas de probleme pour la mettre en oeuvre (merci la FAQ ) mais je ne parvient pas a trouver comment connaitre la progression des transferts, afin d'alimenter ma progressbar, de calculer la vitesse et le temps restant etc ...

    qqun à une idée ?


  2. #2
    Membre averti

    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 43
    Par défaut
    Salut, salut,

    Regarde du côté de l'évènement OnWork du composant IdTCPClient. AWorkCount correspond au nombres de bytes actuellement transférés si je ne me trompe pas. Pour faire une ProgressBar, calcule cela par rapport à la taille totale de ton fichier.

    Voilou, voilou

  3. #3
    Membre confirmé Avatar de souch
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    145
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juin 2003
    Messages : 145
    Par défaut
    marche po avec les IdTCpCLient ou serveur apparament,
    a moins d'une erreur de ma part, voici mon code d'upload depuis le client (neccessite 2 boutons, 2 label et 1 progressbar pour tester (+ une ptite partie serveur afin de recevoir le fichier...)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
     
     
    implementation
     
    {$R *.dfm}
     
    constructor TMonThread.Create;
    begin
      FreeOnTerminate := True;
      inherited Create(false);
    End;
     
    procedure TMonThread.Execute;
    var Fs : TFileStream; AFileName: string; ATcpClient: TIdTCPClient;
    begin
      inherited;
      AFileName:='c:\test.zip';
      ATcpClient:=Form1.IdTCPClient1;
      try
         Fs := TFileStream.Create(AFileName,fmOpenRead,fmShareDenyWrite);
         try
            ATcpClient.WriteLn(Format('TRANS %s',[ExtractFileName(AFileName)]));
            try
              ATcpClient.WriteInteger(Fs.Size);
              ATcpClient.OpenWriteBuffer;
              ATcpClient.WriteStream(Fs);
              ATcpClient.CloseWriteBuffer;
            except
              MessageDlg('error during sending file', mtError, [mbOK], 0);
            end;
         finally
            FreeAndNil(Fs);
         end;
      finally
      Synchronize(action);
      end;
    End;
     
    procedure TMonThread.Action;
    begin
      Form1.Label2.Caption:='Thread End';
    end;
     
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      IdTCPClient1.Connect;
    end;
     
    procedure TForm1.Button2Click(Sender: TObject);
    begin
      TMonThread.Create;
    end;
     
    procedure TForm1.IdTCPClient1Work(Sender: TObject; AWorkMode: TWorkMode;
      const AWorkCount: Integer);
    begin
      if AWorkMode=wmRead then ProgressBar.Position := AWorkCount;
    End;
     
    procedure TForm1.IdTCPClient1WorkBegin(Sender: TObject;
      AWorkMode: TWorkMode; const AWorkCountMax: Integer);
    begin
       if AWorkMode = wmRead then
       begin
          ProgressBar.Max := AWorkCountMax;
          ProgressBar.Position := 0;
       end;
    End;
     
    procedure TForm1.IdTCPClient1WorkEnd(Sender: TObject;
      AWorkMode: TWorkMode);
    begin
      label1.Caption:='End';
      ProgressBar.Position := 0;
    End;
     
    END.

  4. #4
    Membre averti

    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 43
    Par défaut
    Euh, je ne vois pas ce qui cloche ... Ca me semble pourtant correct. Mais là je ne peux pas tester de même que je ne peux pas revoir le code que j'avais fait. Je ne l'avait pas fait pour les composants TCP mais pour du FTP (mais normalement c'est pareil). Je viens de regarder dans la faq, il y a la même méthode pour les composants HTTP.
    Ce serait moi, je ferais un petit ProcessMessages par acquis de conscience (sans conviction)...
    Si d'ici ce soir, j'ai à nouveau accès à mon code, je posterai la partie correspondante.

  5. #5
    Membre confirmé Avatar de souch
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    145
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juin 2003
    Messages : 145
    Par défaut
    merci

    jai testé avec du idhttp et idftp et ca marche ... apparament personne na réussi (enfin sur toute les recherches sur le net que je viens de faire) a faire ca avec un idtcpclient ou serveur ...
    je suis maudit !

    en attendant j'ai bidouller un code assez moyen qui fait trops bricolage, jai du mal !

    ...

  6. #6
    Membre Expert

    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    685
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 685
    Par défaut
    1. Comme les sockets Indy sont bloquants, il faut absolument que ton client soit threadé ou au moins que tu poses un TIdAntiFreeze sur ta fiche pour que les évènements OnWork puissent être appellés.

    2. Pour envoyer le fichier, tu ferais mieux d'utiliser directement les streams (la FAQ devra être corrigée un jour à ce sujet) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
             ATcpClient.WriteInteger(Fs.Size); 
             ATcpClient.WriteStream(Fs);

  7. #7
    Membre confirmé Avatar de souch
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    145
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juin 2003
    Messages : 145
    Par défaut
    Salut, si tu regarde le code que jai posté, tu peut voir que c'est exactement ce que je fait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
       ATcpClient.WriteInteger(Fs.Size); 
       ATcpClient.OpenWriteBuffer; 
       ATcpClient.WriteStream(Fs); 
       ATcpClient.CloseWriteBuffer;
    et aussi que c'est bien dans un Thread;

  8. #8
    Membre Expert

    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    685
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 685
    Par défaut
    Je veux dire sans l'appel aux fonctions de manipulation du buffer.

  9. #9
    Membre confirmé Avatar de souch
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    145
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juin 2003
    Messages : 145
    Par défaut
    Cool !

    en effet, si je retire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
       ATcpClient.OpenWriteBuffer; 
    et
       ATcpClient.CloseWriteBuffer;
    la les evenements onwork fonctionnent !
    je pensait que c'etait indispenssable alors je ni touchait pas ...

    Merci Reisubar, reste plus qu'a faire des fonction pour connaitre vitesse de download etc ....

  10. #10
    Membre confirmé Avatar de souch
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    145
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juin 2003
    Messages : 145
    Par défaut
    heu ... Reisubar si tu est encore dans les murs ...

    en enlevant les appels aux fonctions de manipulation du buffer jai bien mes info onwork etc.. mais je ne parvient pas a liberer le fichier en fin de transfert ...
    a part en fermant le client ou le serveur (selon le sens du transfert)...

    je suis dessus depuis un bout de temps et je ne pige pas d'ou ca vient (mais bon, je ne suis pas un pro... )

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
     
            if (i>0) and (LowerCase(Copy(Line,1,Pred(i)))='trans') then  //Si serveur doit recevoir
            begin
               FileName := IncludeTrailingPathDelimiter(ExtractFilePath(Application.ExeName))
                                + Copy(Line,Succ(i),Length(Line)); //Copier nom de fichier
               Fs := TFileStream.Create(FileName,fmCreate); //Créer le flux
               try
                 try
                   FileSize := AThread.Connection.ReadInteger(); //Lire la taille
     
                   Memo1.Lines.Add('Telechargement ...');
     
                   AThread.Connection.ReadStream(Fs,FileSize,False);
                                   //ici ca bouge plus
     
                   Memo1.Lines.Add('Telechargement terminé !');                AThread.Connection.WriteLn('OK'); //Signaler succès
                 except
                   AThread.Connection.WriteLn('ERR'); //Signaler une erreur
                 end;
               finally
                 FreeAndNil(Fs); //Libérer le flux dans tous les cas
               end;
            end;
    ps: oui je sais je devrai mettre les ajout dans le memo ne Synchronize ...

    je n'ai aucuns message d'erreur, le thread reste ouvert, mon fichier transféré atteint sa taille voulu et est bloqué en lecture/ecriture, en gros, je ne le libre pas ...

    oune idée ?


  11. #11
    Membre Expert

    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    685
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 685
    Par défaut
    C'est bizarre... Est-ce que la valeur reçue dans FileSize est correcte ?

  12. #12
    Membre confirmé Avatar de souch
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    145
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juin 2003
    Messages : 145
    Par défaut
    bha oui ... lol, je suis un peut perdu la ..., a tout les coups j'ai fait une erreur toute bête ...

  13. #13
    Membre confirmé Avatar de souch
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    145
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juin 2003
    Messages : 145
    Par défaut
    jai donc ca coté envoi client
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
         AFileName:='c:\test.zip';
         Fs := TFileStream.Create(AFileName,fmOpenRead,fmShareDenyWrite);
         try
            ATcpClient.WriteLn(Format('TRANS %s',[ExtractFileName(AFileName)]));
            Synchronize(preaction);
            Form1.Memo1.Lines.Add('Envoi du fichier'+AFileName+' de taille :'+IntToStr(Fs.Size)); //la je verifie la taille que jenvoie
            try
              ATcpClient.WriteInteger(Fs.Size); // !
              ATcpClient.WriteStream(Fs);
            except
              Form1.Memo1.Lines.Add('error during sending file');
            end;
         finally
            FreeAndNil(Fs);
         end;

    et ca coté serveur lors d'un envoi vers le serveur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
     
               Fs := TFileStream.Create(FileName,fmCreate); //Créer le flux 
               try 
                 try 
                   FileSize := AThread.Connection.ReadInteger(); //Lire la taille 
     
                   Memo1.Lines.Add('Telechargement ...'); 
     
                   AThread.Connection.ReadStream(Fs,FileSize,False);
    pige pas

  14. #14
    Membre Expert

    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    685
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 685
    Par défaut
    Je ne peux pas t'aider car j'ai la version 10 et pas la 9 mais :

    -> Le code modifiant le memo doit être effectivement dans un synchronize, s'il est exécuté côté serveur,
    -> Une fois le transfert effectué, il faut que tu déconnectes l'autre hôte à un moment ou à un autre (par exemple dans finally).

  15. #15
    Membre confirmé Avatar de souch
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    145
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juin 2003
    Messages : 145
    Par défaut
    ha ... il faut donc bien que je le déconnecte !
    le probleme doit venir de la alors, mais dans mon appli mes clients restent en permanence connéctés au serveur, et ce dernier doit avoir la possibilité d'envoyer et de recevoir des fichiers, ce nest pas super pratique si je doit me deconnecter le serveur ou le client a chaque transfert....
    je vais essayer de trouver un autre moyen
    . . .

    au fait, indy 10 est encore en béta non ?

  16. #16
    Membre confirmé Avatar de souch
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    145
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juin 2003
    Messages : 145
    Par défaut
    Trouvé !

    tu va rire (ou pas selon le temps que je tai fait perdre ... )
    j'avais ajouté une couche de compréssion (avec un TIdCompressionIntercept), et apparament c ca qui me bloquait au final ...
    mea culpa, le reste du code et bon, sans avoir besoin de déconnecter (vu qu'on donne au ReadStream la taille du fichier ...)

    merci encore !

  17. #17
    Membre Expert

    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    685
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 685
    Par défaut
    C'est bien ce qui me semblait, parce que je ne voyais pas de fautes particulières dans ton code...

    Pour Indy10, la béta est assez "mature" pour être utilisé sans problème dans tes projets.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. indy et une barre de progression
    Par m14w dans le forum Delphi
    Réponses: 4
    Dernier message: 04/08/2006, 06h22
  2. Indy FTP (idFTP) faire une barre de progress de transfert
    Par Harry dans le forum Web & réseau
    Réponses: 4
    Dernier message: 09/07/2004, 13h15
  3. Réponses: 3
    Dernier message: 26/07/2002, 23h02
  4. [Kylix] indy sur kylix? pb :-(
    Par NicoLinux dans le forum EDI
    Réponses: 7
    Dernier message: 15/05/2002, 23h32
  5. [Kylix] Runtime error 230 avec INDY
    Par Anonymous dans le forum EDI
    Réponses: 2
    Dernier message: 23/03/2002, 11h51

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo