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

Langage Delphi Discussion :

[D2010] Comment télécharger un fichier depuis un serveur avec InternetReadFile ?


Sujet :

Langage Delphi

  1. #1
    Expert éminent
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 665
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste-programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 665
    Points : 6 980
    Points
    6 980
    Par défaut [D2010] Comment télécharger un fichier depuis un serveur avec InternetReadFile ?
    J'ai un outil qui doit récupérer des fichiers depuis un serveur (sur un réseau interne).
    J'utilisais CopyFileEx, mais cette fonction semble ne pas gérer plusieurs accès à un fichier (sur le serveur) en même temps.

    On m'a conseillé d'utiliser InternetReadFile.
    Ca semble fonctionner, mais la plupart des fichiers récupérés ont la même taille (1,75 ko); et c'est pas bon.

    Voici comment je fais :
    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
    function TFormMaj.TelechargerFichier(const szFichierSource, szFichierDest: String; out szErreur: String): Boolean;
    var
       szSource: String;
       nIndex, nTailleCopiee: Integer;
       hsession : HINTERNET;
       nTailleFichier, nTailleTransferee: Int64;
       hUrlFile: HINTERNET;
       F: File;
       Buffer: Array[1..1024] of Byte;
       nTailleLue: Cardinal;
    begin
       Result := False;
     
       szSource := LowerCase(ExtractFilePath(szFichierSource));
       nIndex := Pos('\maj\', szSource);
       if nIndex > 0 then
       begin
          szSource := Copy(szSource, nIndex + 5, Length(szSource));
          szSource := StringReplace(szSource, '\', '/', [rfReplaceAll, rfIgnoreCase]);
     
          // Connexion.
          hSession := InternetOpen('serveurupdate', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
          try
             if Assigned(hSession) then
             begin
                Gauge.Progress := 0;      nTailleTransferee := 0;      nTailleFichier := GetTailleFichier(szFichierSource);
     
                // Ouverture du fichier.
                hUrlFile := InternetOpenURL(hSession, PChar(_szURL + szSource + ExtractFileName(szFichierSource)), nil, 0, 0, 0);
                if Assigned(hUrlFile) then
                begin
                   try
                      try
                         // Téléchargement du fichier.
                         AssignFile(F, szFichierDest);
                         try
                            {$I-}
                            Rewrite(F, 1);
                            {$I+}
                            if IOResult = 0 then
                            begin
                               repeat
                                  // Copie du bloc.
                                  if InternetReadFile(hUrlFile, @Buffer, SizeOf(Buffer), nTailleLue) then
                                  begin
                                     BlockWrite(F, Buffer, nTailleLue, nTailleCopiee);
                                     ...
                                  end;
                               until(nTailleLue = 0) or (nTailleCopiee <> Integer(nTailleLue));
                            end;
                         finally
                            CloseFile(F);
                         end;
                      except
                         on E: Exception do
                         begin
                            szErreur := 'Échec téléchargement (InternetReadFile):  ' + E.Message;
                            Exit;
                         end;
                      end;
     
                      Result := True;
                   finally
                      InternetCloseHandle(hUrlFile);
                   end;
                end;
             end
             else
                szErreur := 'Échec connexion (InternetOpen):  ' + SysErrorMessage(GetLastError);
          finally
             InternetCloseHandle(hSession);
          end;
       end
       else
          szErreur := 'Erreur :  chemin [' + szFichierSource + '] incorrect !';
    end;
    J'ai fait une recherche sur le forum, mais les fonctions trouvées ressembles fortement à la mienne.
    Qu'est ce que j'ai raté ?

    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. ___ Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.3.2 Entreprise - Delphi 10.4.2 Entreprise - Delphi 11.1 Entreprise
    OpenGL 2.1 - Oracle 10g - Paradox - Interbase (XE) - PostgreSQL (15.4)

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 469
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 469
    Points : 24 905
    Points
    24 905
    Par défaut
    Tu ne compares pas nTailleTransferee et nTailleFichier dans ta fonction, cela te sera utile pour savoir si le fichier a été reçu entier ?

    Tu devrais exploiter un GetLastError si tu as un mauvais retour de InternetReadFile, cela pourrait te mettre sur une piste !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Expert éminent
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 665
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste-programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 665
    Points : 6 980
    Points
    6 980
    Par défaut
    J'ai ajouté l'affichage du GetLastError quand InternetReadFile renvoit faux, mais ça n'arrive jamais.
    J'ai testé après la boucle la différence entre nTailleTransferee et nTailleFichier: j'ai presque tout le temps une différence; nTailleTransferee a une taille fixe, inférieure à nTailleFichier.
    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
                               repeat
                                  // Copie du bloc.
                                  if InternetReadFile(hUrlFile, @Buffer, SizeOf(Buffer), nTailleLue) then
                                  begin
                                     BlockWrite(F, Buffer, nTailleLue, nTailleCopiee);
     
                                     // Affichage.
                                     ...
                                  end
                                  else
                                     AffErreur(ExtractFileName(szFichierSource) + ' >> ' + SysErrorMessage(GetLastError));
                               until(nTailleLue = 0) or (nTailleCopiee <> Integer(nTailleLue));
     
                               if nTailleTransferee <> nTailleFichier then
                                  AffErreur(ExtractFileName(szFichierSource) + ' >> ' + IntToStr(nTailleTransferee) + ' <> ' + IntToStr(nTailleFichier));
    J'ai ensuite remplacé la condition de la boucle par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    until(nTailleTransferee = nTailleFichier);
    Mais, il n'en sort jamais.

    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. ___ Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.3.2 Entreprise - Delphi 10.4.2 Entreprise - Delphi 11.1 Entreprise
    OpenGL 2.1 - Oracle 10g - Paradox - Interbase (XE) - PostgreSQL (15.4)

  4. #4
    Expert éminent
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 665
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste-programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 665
    Points : 6 980
    Points
    6 980
    Par défaut
    J'ai vu dans cette discution http://www.developpez.net/forums/d83...gros-fichiers/ qu'il faut peut-être utiliser InternetQueryDataAvailable avant InternetReadFile.
    J'ai donc fait comme ça :
    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
    Buffer: Array of Byte;
    ...
                               repeat
                                  if InternetQueryDataAvailable(hUrlFile, nTailleALire, 0, 0) then
                                  begin
                                     try
                                        SetLength(Buffer, nTailleALire);
                                     except
                                        on E: Exception do
                                        begin
                                           ShowMessage(E.Message);
                                           AffErreur(ExtractFileName(szFichierSource) + ' >> ' + E.Message);
                                           Exit;
                                        end;
                                     end;
     
                                     // Copie du bloc.
                                     if InternetReadFile(hUrlFile, @Buffer, nTailleALire, nTailleLue) then
                                     begin
                                        BlockWrite(F, Buffer, nTailleLue, nTailleCopiee);
     
                                        // Affichage.
                                        ...
                                     end
                                     else
                                        AffErreur(ExtractFileName(szFichierSource) + ' >> ' + SysErrorMessage(GetLastError));
                                  end;
                               until(nTailleLue = 0) or (nTailleCopiee <> Integer(nTailleLue));
    En pas-à-pas, ca fonctionne au premier tour de boucle.
    Au deuxième tour, au moment de refaire le SetLength, j'ai une violation d'accès.
    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. ___ Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.3.2 Entreprise - Delphi 10.4.2 Entreprise - Delphi 11.1 Entreprise
    OpenGL 2.1 - Oracle 10g - Paradox - Interbase (XE) - PostgreSQL (15.4)

  5. #5
    Membre expérimenté
    Avatar de ouiouioui
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Août 2006
    Messages
    984
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Août 2006
    Messages : 984
    Points : 1 419
    Points
    1 419
    Par défaut
    Ton 1er code semble correct, utilise INTERNET_FLAG_RELOAD pour être sur de retélécharger et pas prendre dans le cache
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    InternetOpenURL(hSession, PChar(_szURL + szSource + ExtractFileName(szFichierSource)), nil, 0, INTERNET_FLAG_RELOAD, 0);
    moi j'utilise un TFileStream
    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
     
    Procedure DownloadFile;
    Var
      hSession, hURL:                                                       HInternet;
      Buffer:                                                                   Array [1 .. 1024] Of Byte;
      BufferLen:                                                              DWord;
      FS:                                                                       TFileStream;
    Begin
        hSession     := InternetOpen('test', INTERNET_OPEN_TYPE_PRECONFIG, '', '', 0);
        FS := TFileStream.Create('c:\00.txt', fmCreate);
        Try
          hURL := InternetOpenURL(hSession, 'http://www.rest.cio/tt.exe', NIL, 0, INTERNET_FLAG_RELOAD, 0);
          Try
            Repeat
              InternetReadFile(hURL, @Buffer, BufferSize, BufferLen);
              FS.WriteBuffer(Buffer, BufferLen);
            Until BufferLen = 0;
          Finally
            InternetCloseHandle(hURL)
          End
        Finally
          InternetCloseHandle(hSession);
          FS.Free;
        End;
    End;
    Il existe 3 sortes de gens: ceux qui savent compter et ceux qui ne savent pas.

  6. #6
    Expert éminent
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 665
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste-programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 665
    Points : 6 980
    Points
    6 980
    Par défaut
    Ca fonctionne pas mieux.
    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
                hUrlFile := InternetOpenURL(hSession, PChar(_szURL + szSource + ExtractFileName(szFichierSource)), nil, 0, INTERNET_FLAG_RELOAD, 0);
                if Assigned(hUrlFile) then
                begin
                   try
                      try
                         // Téléchargement du fichier.
                         FluxFichierDest := TFileStream.Create(szFichierDest, fmCreate);
                         try
                               repeat
                                     // Copie du bloc.
                                     if InternetReadFile(hUrlFile, @Buffer, SizeOf(Buffer), nTailleLue) then
                                     begin
                                        FluxFichierDest.WriteBuffer(Buffer, nTailleLue);
     
                                        // Affichage.
                                        ...
                                     end
                                     else
                                        AffErreur(ExtractFileName(szFichierSource) + ' >> ' + SysErrorMessage(GetLastError));
                               until(nTailleLue = 0);
    En sortie, la taille est toujours fixe (et fausse) pour la plupart des fichiers.
    En fait, à part le premier, j'ai l'impression que c'est tous les suivants qui ne sont pas bon.

    snif
    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. ___ Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.3.2 Entreprise - Delphi 10.4.2 Entreprise - Delphi 11.1 Entreprise
    OpenGL 2.1 - Oracle 10g - Paradox - Interbase (XE) - PostgreSQL (15.4)

Discussions similaires

  1. Impossible de télécharger des fichiers depuis mon serveur
    Par amine55555 dans le forum Mode d'emploi & aide aux nouveaux
    Réponses: 1
    Dernier message: 12/05/2007, 14h15
  2. Réponses: 1
    Dernier message: 19/09/2006, 12h14
  3. Comment télécharger un fichier depuis internet.
    Par horneth dans le forum VB 6 et antérieur
    Réponses: 10
    Dernier message: 18/08/2006, 12h36
  4. Réponses: 5
    Dernier message: 27/06/2006, 10h08
  5. [WebForms]Comment télécharger un fichier depuis le serveur ?
    Par pepin21 dans le forum Général Dotnet
    Réponses: 6
    Dernier message: 26/04/2006, 16h26

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