HTTP download via Socket

HttpRequest and httpRetupResult are used to retrieve a result by querying a URL. To have the gauge, the use of HTTPJauge is oddly independent instead of being a CallBack. In the other hand, it is not possible to limit the download speed. The code below allows it and controls the gauge directly and the speed.

Be careful, this code is not intended to work on https URLs.

PROCEDURE TéléchargeHTTP(bContenu is boolean,sFichierHTTP is string,sFichierDestination is string,bAvecJauge is boolean,sPréfixeJauge is string,nTimeOut is int,nPort is int,sUser is string,sPass is string,sNomDuThread is string,LOCAL sProxy is string)
//bContenu : permet de télécharger le contenu du fichier (vrai) ou seulement l'entête (faux)
//sFichierHTTP : adresse HTTP du fichier sans http:// devant (ex : www.apple.com/fraise.png)
//sFichierDestination : chemin du fichier à créer (en local)
//bAvecJauge : affiche la progression dans la barre de message de la fenêtre appellante (à modifier si on veut faire pointer vers une autre jauge)
//sPréfixeJauge : texte à afficher avant le pourcentage (le tout s'affichera à droite de la jauge dans la barre de message de la fenêtre appelante)
//nTimeOut : durée du timeout (voir doc de la fonction SocketConnecte)
//nPort : port sur lequel faire la connexion HTTP (habituellement le 80)
//sUser : Nom d'utilisateur pour avoir accès en HTTP au fichier sFichierHTTP (voir fichier .htaccess du site)
//sPass : Mot de passe relié à l'utilisateur sUser
//sNomDuThread : nom du thread ayant appelé cette fonction (afin que cette fonction télécharge en tâche de fond)
//sProxy : adresse du proxy intermédiaire (UserProxy:PassProxy@AdresseProxy:PortProxy)
 
//gbAnnule : variable globale booléenne qui indique que le téléchargement doit être arrêté prématurément (vrai), sinon laisser à faux
//gsErreurHTTP : variable globale chaine qui récupère le message d'erreur
//gsAgentHTTP : variable globale chaine contenant l'agent HTTP (voir fonction HTTPRequête / agent utilisateur)
 
ThreadSendSignal(sNomDuThread)
sMsg,sReq is string
sNomSocketHTTP is string = "MonSocketHTTP"
 
sReqDirect is string = [
  GET %1 HTTP/1.1
  Host: %2
  User-Agent: %3
  Connection: keep-alive
]
 
sReqProxy is string = [
  GET %1 HTTP/1.1
  Host: %2
  User-Agent: %3
  Proxy-Connection: keep-alive
  Cache-Control: max-age=0
  Proxy-Authorization: Basic %4
]
 
nJaugeMax,f,nRecu,nSeconde,nRecuParSeconde,nCentieme,nDurée is int
sLigne,sEntête,sJauge,hDiff,sErr,sDomaine,sAcces is string
dhHCur,dhHInit are DateHeures
duDurée1 is Duration
rDébit is real
 
WHEN EXCEPTION IN
  sDomaine=ExtractString(sFichierHTTP,1,"/")
  IF sProxy>"" _AND_ Position(sProxy,"@")>0 THEN 
    sAcces = Crypt(ExtractString(sProxy,1,"@"),"",cryptAnsi,encodeBASE64)
    sProxy = ExtractString(sProxy,2,"@") 
  END
 
  IF SocketConnect(sNomSocketHTTP,(sProxy>"" ? Val(ExtractString(sProxy,2,":")) ELSE nPort),(sProxy>"" ?ExtractString(sProxy,1,":") ELSE sDomaine),nTimeOut)=False THEN
    gsErreurHTTP="Erreur de connexion : "+ErrorInfo(errMessage)
  ELSE
    SocketChangeTransmissionMode(sNomSocketHTTP,SocketNoEndTag)
    //gestion du proxy
    IF sProxy>"" THEN
      sReq=StringBuild(sReqProxy,"http://"+sFichierHTTP,sDomaine,gsAgentHTTP,sAcces)
    ELSE
      sReq=StringBuild(sReqDirect,Middle(sFichierHTTP,Length(sDomaine)+1),sDomaine,gsAgentHTTP)
    END
    //gestion de l'authentification au serveur lui-même
    IF sUser>"" THEN sReq+=CR+"Authorization: Basic "+Crypt(sUser+":"+sPass,"",cryptAnsi,encodeBASE64)
    sReq+=CR+CR
 
    IF SocketWrite(sNomSocketHTTP,sReq) THEN
      nRecu=0;nRecuParSeconde=0
      //mémorise la date et heure pour afficher une jauge chaque seconde
      dhHInit=DateSys()+TimeSys();nSeconde=Val(Middle(dhHInit,13,2));nCentieme=Val(Middle(dhHInit,15,2))
      WHILE SocketExist(sNomSocketHTTP)=True
        sMsg = SocketRead(sNomSocketHTTP,True)
        IF NOT sMsg = "" THEN 
          IF nRecu=0 THEN
            sEntête=ExtractString(sMsg,1,CR+CR);sMsg=ExtractString(sMsg,2,CR+CR)
            IF NOT (ExtractString(sEntête,1,CR)="HTTP/1.1 200 OK" OR ExtractString(sEntête,1,CR)="HTTP/1.0 200 OK") THEN 
              gsErreurHTTP="Erreur donnée par le serveur HTTP ("+Middle(ExtractString(sEntête,1,CR),10)+")"
              BREAK
            END
            IF NOT bContenu THEN
              gsErreurHTTP=sEntête
              BREAK
            END
            //trouve la taille du fichier à télécharger pour initialiser la jauge
            FOR EACH STRING sLigne OF sEntête SEPARATED BY CR
              IF Left(sLigne,15)="Content-Length:" THEN nJaugeMax=Val(ExtractString(sLigne,2,":"))
            END
            fDelete(sFichierDestination);f=fCreate(sFichierDestination)
            IF f=-1 THEN 
              gsErreurHTTP="Impossible créer le fichier de destination : "+ErrorInfo(errMessage)
              BREAK
            END
          ELSE
            IF gbAnnule THEN BREAK
          END
          IF NOT f=-1 THEN
            nRecu+=Length(sMsg)
            fWrite(f,sMsg)
 
            dhHCur=DateSys()+TimeSys();nRecuParSeconde+=Length(sMsg)
            IF bAvecJauge _AND_ NOT nSeconde=Val(Middle(dhHCur,13,2)) THEN
              sJauge=NumToString(Round(nRecu/nJaugeMax*100,1),"3.1fs")+"%"  // reçu à "+TailleVersChaîne(nRecuParSeconde)+"/s"
              Gauge(nRecu,nJaugeMax,sPréfixeJauge+[" "]+sJauge)
              nRecuParSeconde=0
              dhHCur=DateSys()+TimeSys();nSeconde=Val(Middle(dhHCur,13,2));nCentieme=Val(Middle(dhHCur,15,2))
            END
            IF nRecu=nJaugeMax THEN
              hDiff=DateTimeDifference(dhHInit,dhHCur)
              IF bAvecJauge THEN
                duDurée1 = StringToDuration(hDiff,durationCenti) 
                nDurée=duDurée..Day*86400+duDurée..Hour*3600+duDurée..Minute*60+duDurée..Second 
                rDébit=Round(nJaugeMax/nDurée,2)
                Gauge(nRecu,nJaugeMax,sPréfixeJauge+[" "]+"100,0%")  // reçu à "+TailleVersChaîne(rDébit)+"/s en moyenne")
              END
              fClose(f);BREAK
            END
          END
        ELSE 
          BREAK
        END
      END
      IF f<>-1 THEN fClose(f)
 
      IF bContenu THEN
        IF (fFileExist(sFichierDestination) _AND_ fSize(sFichierDestination)=nJaugeMax) THEN
          gsErreurHTTP=""
        ELSE IF gsErreurHTTP THEN
          gsErreurHTTP="Fichier vide ou incomplet."
        END
      END
    ELSE
      gsErreurHTTP="Erreur durant le téléchargement HTTP : "+ErrorInfo(errMessage)
    END
    SocketClose(sNomSocketHTTP)
  END
DO
  SocketClose(sNomSocketHTTP)
  gsErreurHTTP="Erreur durant le téléchargement HTTP : "+ExceptionInfo(errMessage)
END

To run the download in the background, it is advisable (at least the procedure is built like this) to call it in a separate thread:

PROCEDURE sTéléchargeHTTP(sFichierHTTP is string,sFichierDestination is string="",bAvecJauge is boolean=False,sPréfixeJauge is string="",nTimeOut is int = 5000,nPort is int = 80,sUser is string="", sPass is string="",sNomDuThread is string = threadMain,sProxy is string = "")
sNomThread is string = "MonThreadHTTP"
gsErreurHTTP=""
ThreadExécute(sNomThread,threadNormal,TéléchargeHTTP,(sFichierDestination>""),sFichierHTTP,sFichierDestination,bAvecJauge,sPréfixeJauge,nTimeOut,nPort,sUser,sPass,sNomDuThread,sProxy);ThreadWaitSignal()
WHILE ThreadState(sNomThread)=threadRunning
  IF gbAnnule THEN ThreadStop(sNomThread)
  Multitask(-5)
END
RESULT gsErreurHTTP
Ce site n'a aucun lien avec la société PC SOFT®. Les marques "WinDev" et "WebDev" sont des marques déposées de la société PC SOFT.