2009-07-20 4 views
3

J'ai cette méthode pour transférer des fichiers via un serveur FTP:FTP en C# retournant le fichier corrompu, pourquoi?

private void TransferNeededFiles(IEnumerable<string> filenames) 
{ 
    foreach (var filename in filenames) 
    { 
     var request = WebRequest.Create(new Uri(@"ftp://{0}/{1}".Fill(Config.ServerUri, filename))) as FtpWebRequest; 

     if (request != null) 
     { 
      request.Credentials = new NetworkCredential(Config.Username, Config.Password); 

      request.Method = WebRequestMethods.Ftp.DownloadFile; 
      using (var streamReader = new StreamReader(request.GetResponse().GetResponseStream())) 
      { 
       var fileStream = new FileStream(@"{0}/{1}".Fill(Config.DestinationFolderPath, filename), FileMode.Create); 

       var writer = new StreamWriter(fileStream); 
       writer.Write(streamReader.ReadToEnd()); 
       writer.Flush(); 
       writer.Close(); 

       fileStream.Close(); 
      } 
     } 
    } 
} 

Un fichier .gz, inclus dans la liste des noms de fichiers, est toujours corrompu. Lorsque j'essaie de copier à partir de ftp en utilisant Windows Explorer, le fichier n'est pas corrompu. Savez-vous ce qui se passe?

+0

Etes-vous sûr d'utiliser le transfert binaire et non ASCII? –

+0

J'utilise ce code ci-dessus. Je ne spécifie ni ascii ni binaire, cela pourrait-il être le problème? –

+0

Vérifiez également UseBinary http://msdn.microsoft.com/en-us/library/system.net.ftpwebrequest.usebinary.aspx. –

Répondre

7

Le problème est cette ligne:

writer.Write(streamReader.ReadToEnd()); 

StreamReader.ReadToEnd() retourne une chaîne codée Unicode. Vous voulez quelque chose qui lira l'octet de flux pour byte.

+0

Je pense que Joel l'a cloué (comme d'habitude). Vous aurez probablement envie de lire le flux en morceaux aussi au lieu de tout à la fois. –

3

Reader s et Writer s fonctionnent avec des caractères Unicode. Pour transférer des données binaires, vous voulez travailler avec des octets bruts, donc vous devriez utiliser Stream s. Vous pouvez copier d'un flux à l'autre avec une boucle comme ce qui suit:

BufferedStream inputStream, outputStream; 
byte[] buffer = new byte[4096]; 
int bytesRead; 

while ((bytesRead = inputStream.Read(buffer)) > 0) 
{ 
    outputStream.Write(buffer, 0, bytesRead); 
} 

Une bonne chose à ce sujet est qu'il sera également utiliser uniquement une quantité fixe de mémoire plutôt que de lire le fichier en mémoire à la fois.

Questions connexes