Blocage avec plusieurs téléchargements en WebClient

cs_Skeatwin Messages postés 25 Date d'inscription samedi 17 mai 2008 Statut Membre Dernière intervention 19 juillet 2011 - 18 juil. 2011 à 20:25
 Utilisateur anonyme - 20 juil. 2011 à 00:03
Bonjour ,

J'ai écrit un programme qui met à jour des fichiers chez les clients.
J'utilise pour cela un serveur qui vérifie à chaque connexion d'un client, une base de donnée MySQL où sont stocké toutes ces mises à jour, puis le serveur les communique les résultats au client au travers d'un socket.
Une fois que le client reçois toutes ces donnés, il entame le processus de mise à jour. Pour chaque ligne reçu, le client utilise un WebClient pour télécharger de façon asynchrone (pour avoir le pourcentage et le débit).

J'ai plusieurs problèmes:
1. Sur certain FTP j’obtiens une erreur 500 (commande ou syntaxe incorrecte) au bout de quelques fichier téléchargés.
2. Au bout environs de 20 fichiers téléchargés, le téléchargement commence à ce bloqué quelques secondes (en cours de route) puis continue.

Il faut savoir pour mon 2ème problème: plus on avance plus les blocages sont nombreux et font chuter DRASTIQUEMENT le débit de téléchargement.
J'avais un autre problème avant que j'ai résolu: plus on avancer plus le débit chuté (mais je n'avais pas de blocage). Cela venait du fait que j'instancier un WebClient pour chaque fichier sans supprimer l'ancien.

Si vous avez une idée n'hésitez pas ^^

Voilà mon code, j'utilise la méthode Télécharger(MonURL,MonURLlocal,WarpID pour une redirection,ForcerTailleFichier):
Imports System.IO.FileSystemInfo
'/// Module de téléchargement asynchrone avec retour de Armand SZYPURA /// v 4.3


Module Téléchargement

#Region "Déclarations"

    'Déclaration des variable de Téléchargement
    Public StatueTéléchargement As Integer 0 '0 pas de DL : 1 = DL en cour
    Public PourcentageTéléchargement, VitesseTéléchargement
    Public MoTotal_à_Télécharger As Double
    Public MoTéléchargé As Double
    Public Seconde_restanteTéléchargement, Minute_restanteTéléchargement, Heure_restanteTéléchargement, TempsRestantCompletTéléchargement

    Dim WC As System.Net.WebClient 'On crée un web client pour Download

    Dim TimerUpTime_Téléchargement As New System.Windows.Forms.Timer 'On crée aussi un timer pour le temp
    Dim TimerUpPct_Téléchargement As New System.Windows.Forms.Timer 'On crée aussi un timer pour les actualisation des stats
    Dim downloadedBytes As Long
    Dim totalSize As Long = 0
    Dim Temps_Téléchargement, TempsRestant_Téléchargement, pctNat, tmp


    'Déclaration des variable de Upload
    Public StatueUpload As Integer 0 '0 pas de DL : 1 = DL en cour
    Public PourcentageUpload, VitesseUpload
    Public MoTotal_à_Uploader As Double
    Public MoUploadé As Double
    Public Seconde_restanteUpload, Minute_restanteUpload, Heure_restanteUpload, TempsRestantCompletUpload

    Dim WCUpload As System.Net.WebClient 'On crée un web client pour Upload

    Dim TimerUpTime_Upload As New System.Windows.Forms.Timer 'On crée aussi un timer pour le temp
    Dim TimerUpPct_Upload As New System.Windows.Forms.Timer 'On crée aussi un timer pour les actualisation des stats
    Dim UploadedBytes As Long
    Dim totalSize_Upload As Long = 0
    Dim Temps_Upload, TempsRestant_Upload, pctNat_Upload, tmp2, WarpExit

#End Region
   

#Region "Download"

    Private HandlerExistD As Boolean = False

    Public Sub Télécharger(ByVal Url As String, ByVal Chemin_Enregistrement As String, Optional ByVal WarpID As Int16 -1, Optional ByVal sizeMO As Double -1)
        WarpExit = WarpID
        StatueTéléchargement = 1 'On averti l'appli que on Dl un fichier.

        'Réinitialisation des valeurs.
        Temps_Téléchargement = 0
        MoTéléchargé = 0
        MoTotal_à_Télécharger = 0
        PourcentageTéléchargement = 0
        VitesseTéléchargement = ""

        If sizeMO > -1 Then 'Prise en compte de la taille forcée.
            totalSize = sizeMO * 1000000D 'Taille total en bytes
            MoTotal_à_Télécharger = Math.Round(sizeMO, 2) 'Taille total en MO
        End If

        fermerConnexion()
        CreatHandlerD()

        TimerUpPct_Téléchargement.Interval = 100
        TimerUpTime_Téléchargement.Interval = 1000
        TimerUpTime_Téléchargement.Start()
        TimerUpPct_Téléchargement.Start()

        Dim Dossier As String = "Inconnu"
        Try
            Dossier = My.Computer.FileSystem.GetParentPath(Chemin_Enregistrement)

            If My.Computer.FileSystem.DirectoryExists(Dossier) = False Then
                My.Computer.FileSystem.CreateDirectory(Dossier)
            End If

        Catch ex As Exception
            Log_erreur([String].Format("Impossible de créer le dossier '{0}'. (Cause: {1})", Dossier, ex.Message))
            Warp(2)
            Exit Sub
        End Try

        WC.DownloadFileAsync(New Uri(Url), Chemin_Enregistrement) 'On télécharge enfin le fichier.

    End Sub

    Public Sub CreatHandlerD()
        If WC Is Nothing Then
            WC = New System.Net.WebClient
            WC.Proxy = Nothing
            AddHandler WC.DownloadProgressChanged, AddressOf OnDownloadProgressChanged 'On ajoute l'évènement "Que se passe t-il quand la progession a changer ?"
            AddHandler WC.DownloadFileCompleted, AddressOf OnFileDownloadCompleted 'On ajoute l'évènement "Que se passe t-il quand le fichier a fini d'être télécharger ?"
        End If
        If HandlerExistD = False Then
          
            AddHandler TimerUpPct_Téléchargement.Tick, AddressOf TimerUpPct_Téléchargement_Tick
            AddHandler TimerUpTime_Téléchargement.Tick, AddressOf TimerUpTime_Téléchargement_Tick
            HandlerExistD = True
        End If
    End Sub

    Private Sub TimerUpTime_Téléchargement_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs)

        'On avance le temps de 1000 milisecondes.
        Temps_Téléchargement += 1

        Try

            VitesseTéléchargement = CInt((downloadedBytes / 1000) / Temps_Téléchargement)
            If VitesseTéléchargement > 999 Then
                VitesseTéléchargement = Math.Round(VitesseTéléchargement / 1000, 2) & " Mo/s"
            Else
                VitesseTéléchargement = VitesseTéléchargement & " Ko/s"
            End If
            'TempsRestant_Téléchargement = ((totalSize * Temps_Téléchargement) / downloadedBytes) - Temps_Téléchargement

            'Seconde_restanteTéléchargement = CInt((TempsRestant_Téléchargement Mod 3600) Mod 60)
            'Minute_restanteTéléchargement = CInt((TempsRestant_Téléchargement / 60) Mod 60)
            'Heure_restanteTéléchargement = CInt(TempsRestant_Téléchargement / 3600)
            'If Seconde_restanteTéléchargement < 10 Then
            '    Seconde_restanteTéléchargement = "0" & Seconde_restanteTéléchargement
            'End If

            ''Temps restant
            'TempsRestantCompletTéléchargement = ""

            'If Heure_restanteTéléchargement = 1 Then
            '    TempsRestantCompletTéléchargement = "1 heure "
            'ElseIf Heure_restanteTéléchargement > 0 Then
            '    TempsRestantCompletTéléchargement = Heure_restanteTéléchargement & " heures "
            'End If
            'If Minute_restanteTéléchargement = 0 And Heure_restanteTéléchargement > 0 Then
            '    TempsRestantCompletTéléchargement = TempsRestantCompletTéléchargement & "0 minute "
            'ElseIf Minute_restanteTéléchargement = 1 Then
            '    TempsRestantCompletTéléchargement = TempsRestantCompletTéléchargement & "1 minute "
            'ElseIf Minute_restanteTéléchargement > 1 Then
            '    TempsRestantCompletTéléchargement = TempsRestantCompletTéléchargement & Minute_restanteTéléchargement & " minutes "
            'End If
            'If Seconde_restanteTéléchargement 0 Or Seconde_restanteTéléchargement 1 Then
            '    TempsRestantCompletTéléchargement = TempsRestantCompletTéléchargement & Seconde_restanteTéléchargement & " seconde"
            'Else
            '    TempsRestantCompletTéléchargement = TempsRestantCompletTéléchargement & Seconde_restanteTéléchargement & " secondes"
            'End If

        Catch ex As Exception
            TempsRestantCompletTéléchargement = "Inconnu"
        End Try

    End Sub

    Private Sub TimerUpPct_Téléchargement_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs)
        'On convertit les bytes téléchargés en Mo.
        MoTéléchargé = Math.Round(downloadedBytes / 1000000, 2)

        If MoTotal_à_Télécharger > 0 Then
            tmp = (MoTéléchargé / MoTotal_à_Télécharger) * 100
            If tmp > 100 Then
                PourcentageTéléchargement = 100
            Else
                PourcentageTéléchargement = tmp
            End If
        End If
    End Sub

    Sub fermerConnexion()
        If Not WC Is Nothing Then
            RemoveHandler WC.DownloadProgressChanged, AddressOf OnDownloadProgressChanged 'On ajoute l'évènement "Que se passe t-il quand la progession a changer ?"
            RemoveHandler WC.DownloadFileCompleted, AddressOf OnFileDownloadCompleted 'On ajoute l'évènement "Que se passe t-il quand le fichier a fini d'être télécharger ?"
            WC.CancelAsync()
            WC.Dispose()
            WC = Nothing
            GC.Collect()
        End If
    End Sub

    Sub TéléchargerRapidement(ByVal Url As String, ByVal Chemin_Enregistrement As String)
        WC.DownloadFileAsync(New Uri(Url), Chemin_Enregistrement)
    End Sub

    Public Sub AnnulerTéléchargement()
        WC.CancelAsync()
    End Sub

    Private Sub OnFileDownloadCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.AsyncCompletedEventArgs)
            'Que se passe t-il quand le fichier a fini d'être télécharger ?

            TimerUpTime_Téléchargement.Stop()
            TimerUpPct_Téléchargement.Stop()

            StatueTéléchargement = 0
            VitesseTéléchargement = ""


            If e.Cancelled Then 'Annulé




            ElseIf Not e.Error Is Nothing Then 'Une érreur est survenue
                Log_erreur("Erreur de téléchargement du packet n°" & Packet_Actu & " de la mise à jour n°" & UpFait + 1 & ". (Cause: " & e.Error.ToString & ")")
                Warp(2)




            Else 'Fichier téléchargé correctement
                Warp(WarpExit)



            End If
    End Sub

    Private Sub OnDownloadProgressChanged(ByVal sender As Object, ByVal e As System.Net.DownloadProgressChangedEventArgs)
        'Que se passe t-il quand la progession a changer ?

        'If e.TotalBytesToReceive <> totalSize And e.TotalBytesToReceive > 0 Then 'Si la taille du fichier proposé par le FTP est différente de celle forcé et plus > que 0 alors...

        '    'On attribue cette taille comme size global.
        '    totalSize = e.TotalBytesToReceive

        '    'On convertit cette taille en Mo pour plus de facilité.
        '    MoTotal_à_Télécharger = Math.Round(totalSize / 1000000, 2)

        'End If
        'Bytes reçu jusqu'à présent.
        downloadedBytes = e.BytesReceived
        'Pourcentage natif géré par l'api
        pctNat = e.ProgressPercentage
    End Sub


#End Region

#Region "Upload"

    Private HandlerExistU As Boolean = False

    Public Sub Uploader(ByVal Fichier_à_Up As String, ByVal URL As String, Optional ByVal WarpID As Int16 = -1)
        WarpExit = WarpID

        If My.Computer.FileSystem.FileExists(Fichier_à_Up) = True Then
            totalSize_Upload = My.Computer.FileSystem.GetFileInfo(Fichier_à_Up).Length
            MoTotal_à_Uploader = Math.Round(totalSize_Upload / 1000000, 2) 'Taille total en MO
        Else
            MsgBox("Le fichier à uploader n'existe pas !", 16)
            Exit Sub
        End If

        StatueUpload = 1 'On averti l'appli que on Upload un fichier.

        'Réinitialisation des valeurs.
        Temps_Upload = 0
        MoUploadé = 0
        PourcentageUpload = 0
        VitesseUpload = 0

        CreatHandlerU()

        TimerUpPct_Upload.Interval = 10
        TimerUpTime_Upload.Interval = 100
        TimerUpTime_Upload.Start()
        TimerUpPct_Upload.Start()

        WCUpload.UploadFileAsync(New Uri(URL), Fichier_à_Up) 'On Charge enfin le fichier.
    End Sub

    Public Sub CreatHandlerU()
        If HandlerExistU = False Then
            WCUpload = New System.Net.WebClient
            AddHandler WCUpload.UploadProgressChanged, AddressOf OnUploadProgressChanged 'On ajoute l'évènement "Que se passe t-il quand la progession a changer ?"
            AddHandler WCUpload.UploadFileCompleted, AddressOf OnFileUploadCompleted 'On ajoute l'évènement "Que se passe t-il quand le fichier a fini d'être télécharger ?"
            AddHandler TimerUpPct_Upload.Tick, AddressOf TimerUpPct_Upload_Tick
            AddHandler TimerUpTime_Upload.Tick, AddressOf TimerUpTime_Upload_Tick
            HandlerExistU = True
        End If
    End Sub

    Sub UploaderRapidement(ByVal Fichier_à_Up As String, ByVal URL As String)
        WCUpload.UploadFileAsync(New Uri(URL), Fichier_à_Up)
    End Sub

    Public Sub AnnulerUpload()
        WCUpload.CancelAsync()
    End Sub

    Sub fermerConnexion_Upload()
        WCUpload.Dispose()
    End Sub

    Private Sub OnFileUploadCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.AsyncCompletedEventArgs)
        'Que se passe t-il quand le fichier a fini d'être uploadé ?

        TimerUpTime_Upload.Stop()
        TimerUpPct_Upload.Stop()

        StatueUpload = 0
        VitesseUpload = "0 Ko/s"

        If e.Cancelled Then 'Annulé
            MsgBox("L'upload à été annulé.", 48, "Upload annulé")
            '------------------------------------------------------------------------
            'Code à exécuter en cas d'annulation
            '------------------------------------------------------------------------




        ElseIf Not e.Error Is Nothing Then 'Une érreur est survenue
            MsgBox("Erreur lors de l'upload: " & e.Error.Message, 16, "Erreur de l'upload")
            '------------------------------------------------------------------------
            'Code à exécuter en cas d'érreur:
            '------------------------------------------------------------------------




        Else 'Fichier uploadé correctement
            MsgBox("Fichier uploadé correctement !", 64, "Uploadé !")
            '------------------------------------------------------------------------
            'Code à exécuter en cas de réusite:
            '------------------------------------------------------------------------



        End If

    End Sub

    Private Sub OnUploadProgressChanged(ByVal sender As Object, ByVal e As System.Net.UploadProgressChangedEventArgs)
        'Que se passe t-il quand la progession a changer ?

        'Bytes reçu jusqu'à présent.
        UploadedBytes = e.BytesSent
        'Pourcentage natif géré par l'api
        pctNat_Upload = e.ProgressPercentage
    End Sub

    Private Sub TimerUpTime_Upload_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs)

        'On avance le temps de 100 milisecondes.
        Temps_Upload += 0.1

        Try

            VitesseUpload = CInt((UploadedBytes / 1000) / Temps_Upload)
            If VitesseUpload > 999 Then
                VitesseUpload = Math.Round(VitesseUpload / 1000, 2) & " Mo/s"
            Else
                VitesseUpload = VitesseUpload & " Ko/s"
            End If
            TempsRestant_Upload = ((totalSize_Upload * Temps_Upload) / UploadedBytes) - Temps_Upload

            Seconde_restanteUpload = CInt((TempsRestant_Upload Mod 3600) Mod 60)
            Minute_restanteUpload = CInt((TempsRestant_Upload / 60) Mod 60)
            Heure_restanteUpload = CInt(TempsRestant_Upload / 3600)
            If Seconde_restanteUpload < 10 Then
                Seconde_restanteUpload = "0" & Seconde_restanteUpload
            End If

            'Temps restant
            TempsRestantCompletUpload = ""

            If Heure_restanteUpload = 1 Then
                TempsRestantCompletUpload = "1 heure "
            ElseIf Heure_restanteUpload > 0 Then
                TempsRestantCompletUpload = Heure_restanteUpload & " heures "
            End If
            If Minute_restanteUpload = 0 And Heure_restanteUpload > 0 Then
                TempsRestantCompletUpload = TempsRestantCompletUpload & "0 minute "
            ElseIf Minute_restanteUpload = 1 Then
                TempsRestantCompletUpload = TempsRestantCompletUpload & "1 minute "
            ElseIf Minute_restanteUpload > 1 Then
                TempsRestantCompletUpload = TempsRestantCompletUpload & Minute_restanteUpload & " minutes "
            End If
            If Seconde_restanteUpload 0 Or Seconde_restanteUpload 1 Then
                TempsRestantCompletUpload = TempsRestantCompletUpload & Seconde_restanteUpload & " seconde"
            Else
                TempsRestantCompletUpload = TempsRestantCompletUpload & Seconde_restanteUpload & " secondes"
            End If

        Catch ex As Exception
            TempsRestantCompletUpload = "Inconnu"
        End Try

    End Sub

    Private Sub TimerUpPct_Upload_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs)
        'On convertit les bytes téléchargés en Mo.
        MoUploadé = Math.Round(UploadedBytes / 1000000, 2)

        If MoTotal_à_Uploader > 0 Then
            tmp2 = (MoUploadé / MoTotal_à_Uploader) * 100
            If tmp2 > 100 Then
                PourcentageUpload = 100
            Else
                PourcentageUpload = tmp2
            End If
        End If
    End Sub


#End Region


End Module

3 réponses

cs_Skeatwin Messages postés 25 Date d'inscription samedi 17 mai 2008 Statut Membre Dernière intervention 19 juillet 2011
19 juil. 2011 à 14:19
J'ai essayer en changeant de méthode (les HttpRequest et FtpRequest) et je n'est plus l'erreur 500. Par-contre pour le serveur FTP filezilla, j'ai toujours ce problème de blocage au bout de quelques fichiers téléchargés, maintenant avec plus de recule je peut dire que ces blocage se font par deux. En effet quelques secondes après le blocage, le téléchargement reprend et télécharge 2 fichiers et hop sa se rebloque, etc...
0
Utilisateur anonyme
19 juil. 2011 à 23:56
Salut,
Puisque tu utilises le protocole FTP pour le transfert de tes fichiers, pourquoi ne te sers-tu pas tout simplement l'espace de noms My qui contient tout ce qu'il te faut en une ligne de code :
'upload
My.Computer.Network.UploadFile("chemin\fichier.ext", "ftp://login:pass@serveurftp.com/dossier/fichier.ext")
'download
My.Computer.Network.DownloadFile("ftp://login:pass@serveurftp.com/dossier/fichier.ext", "chemin\fichier.ext")

De plus, en observant l'intellisense de visual studio (suggestion d'écriture), tu remarquera également que parmi les surcharges de ces méthodes, il est possible d'afficher une progression de l'opération.

Bonne soirée.
0
Utilisateur anonyme
20 juil. 2011 à 00:03
J'oublie aussi une chose importante.
Un FtpWebRequest serait peut être plus adapté qu'un WebClient pour ce que tu souhaites faire.
0
Rejoignez-nous