2010-02-15 5 views
6

J'ai besoin de télécharger un gros fichier par programme avant de le traiter. Quelle est la meilleure façon de faire cela? Comme le fichier est volumineux, je souhaite un délai spécifique pour que je puisse sortir de force.Comment télécharger un gros fichier par programmation en C#

Je connais WebClient.DownloadFile(). Mais il ne semble pas y avoir de délai spécifique pour attendre la sortie forcée.

try 
{ 
    WebClient client = new WebClient(); 
    Uri uri = new Uri(inputFileUrl); 
    client.DownloadFile(uri, outputFile); 
} 
catch (Exception ex) 
{ 
    throw; 
} 

Une autre façon consiste à utiliser une ligne de commande utilitaire (wget) pour télécharger le fichier et le feu de la commande en utilisant ProcessStartInfo et le processus d'utilisation WaitForExit (int ms) de sortie de force.

ProcessStartInfo startInfo = new ProcessStartInfo(); 
//set startInfo object 

try 
{ 
    using (Process exeProcess = Process.Start(startInfo)) 
    { 
     //wait for time specified 
     exeProcess.WaitForExit(1000 * 60 * 60);//wait till 1m 

     //check if process has exited 
     if (!exeProcess.HasExited) 
     { 
      //kill process and throw ex 
      exeProcess.Kill(); 
      throw new ApplicationException("Downloading timed out"); 
     } 
    } 
} 
catch (Exception ex) 
{ 
    throw; 
} 

Y a-t-il un meilleur moyen? S'il vous plaît aider. Merci.

+0

Quelle est la uri ? est-ce ftp? – t0mm13b

Répondre

16

Utilisez un WebRequest et obtenez le response stream. Lisez ensuite dans la réponse les blocs de flux d'octets et écrivez chaque bloc dans le fichier de destination. De cette façon, vous pouvez contrôler quand arrêter si le téléchargement prend trop de temps, comme vous obtenez le contrôle entre les morceaux et vous pouvez décider si le téléchargement a expiré basé sur une horloge:            

 DateTime startTime = DateTime.UtcNow; 
     WebRequest request = WebRequest.Create("http://www.example.com/largefile"); 
     WebResponse response = request.GetResponse(); 
     using (Stream responseStream = response.GetResponseStream()) { 
      using (Stream fileStream = File.OpenWrite(@"c:\temp\largefile")) { 
       byte[] buffer = new byte[4096]; 
       int bytesRead = responseStream.Read(buffer, 0, 4096); 
       while (bytesRead > 0) {  
        fileStream.Write(buffer, 0, bytesRead); 
        DateTime nowTime = DateTime.UtcNow; 
        if ((nowTime - startTime).TotalMinutes > 5) { 
         throw new ApplicationException(
          "Download timed out"); 
        } 
        bytesRead = responseStream.Read(buffer, 0, 4096); 
       } 
      } 
     } 
+0

@orip, comment est-ce compliqué? – juan

+0

@Juan, Pour un c'est synchrone. La version asynchrone de cet exemple serait très différente. Mais il jette aussi la façade WebClient, très conviviale, qui cache les trucs de gestion de flux qui sont en grande partie hors de propos dans 90% des cas. – Josh

+1

orip, votre code est beaucoup plus simple. l'un des avantages de l'utilisation du code de Remus est que je peux savoir quelle partie du fichier est téléchargée. – hIpPy

7

Comment à propos de l'utilisation de DownloadFileAsync dans la classe WebClient. Ce qui est cool à propos de cette route, c'est que vous pouvez annuler l'opération en appelant le CancelAsync si cela prend trop de temps. Fondamentalement, appelez cette méthode, et si un certain laps de temps s'écoule, appelez Cancel.

4

posée ici: C#: Downloading a URL with timeout

Solution la plus simple:

public string GetRequest(Uri uri, int timeoutMilliseconds) 
{ 
    var request = System.Net.WebRequest.Create(uri); 
    request.Timeout = timeoutMilliseconds; 
    using (var response = request.GetResponse()) 
    using (var stream = response.GetResponseStream()) 
    using (var reader = new System.IO.StreamReader(stream)) 
    { 
     return reader.ReadToEnd(); 
    } 
} 

Une meilleure solution (plus souple) est this answer à la même question, sous la forme d'une classe d'aide WebClientWithTimeout.

+4

Le paramètre webrequest.timeout ne mesure que le temps de réception des en-têtes de réponse HTTP et non le temps total avant que le corps de la réponse ne soit téléchargé. C'est à dire. cela affecte le temps avant que GetResponse ne retourne. –

+0

Bon point, je n'étais pas au courant de ça – orip

2

Vous pouvez utiliser DownloadFileAsync comme @BFree dit et puis essayer avec les événements de WebClient suivants

protected virtual void OnDownloadProgressChanged(DownloadProgressChangedEventArgs e); 
protected virtual void OnDownloadFileCompleted(AsyncCompletedEventArgs e); 

Ensuite, vous pouvez connaître le pourcentage d'avancement

e.ProgressPercentage 

Hope this helps

Questions connexes