2009-10-07 15 views
3

J'essaie de télécharger des fichiers à partir d'un serveur ftp en utilisant C# et ftpwebrequest. Je peux obtenir les octets en utilisant BinaryReader, mais quand j'essaie de lire le flux en utilisant br.ReadBytes (int), j'obtiens une erreur que BinaryReader ne supporte pas les opérations de recherche.C# BinaryReader "flux ne supporte pas les opérations de recherche"

Est-ce que quelqu'un sait comment lire au mieux les octets pour pouvoir les écrire dans un fichier?

est ici la méthode complète:

public void DownloadFile(String fileName) 
    { 
     Logger.Info("starting to download file: " + fileName); 

     try 
     { 
      var downloadFileRequest = (FtpWebRequest)WebRequest.Create(FtpServer + "//" + fileName); 
      downloadFileRequest.Credentials = new NetworkCredential(FtpUsername,FtpPassword); 
      downloadFileRequest.Method = WebRequestMethods.Ftp.DownloadFile; 
      downloadFileRequest.UseBinary = true; 

      ServicePoint sp = downloadFileRequest.ServicePoint; 
      sp.ConnectionLimit = 2; 

      Logger.Info("getting ftp response for download file for " + fileName); 

      try 
      { 
       var downloadResponse = (FtpWebResponse)downloadFileRequest.GetResponse(); 

       Logger.Info("getting ftp response stream for " + fileName); 

       try 
       { 
        Stream downloadStream = downloadResponse.GetResponseStream(); 

        Logger.Info("File Download status: {0}", downloadResponse.StatusDescription.Trim()); 

        Logger.Info("getting binary reader for " + fileName); 

        try 
        { 
         using (var downloadReader = new BinaryReader(downloadStream)) 
         { 
          String destinationFilePath= Path.Combine(LocalFolder, fileName); 

          Logger.Info("writing response stream to " + destinationFilePath); 

          try 
          { 
           using (var downloadWriter = new BinaryWriter(System.IO.File.Open(destinationFilePath, FileMode.Create))) 
           { 
            downloadWriter.Write(downloadReader.ReadBytes((int)downloadStream.Length)); 
           } 

           Logger.Info("successfully saved " + destinationFilePath); 

          } 
          catch (Exception ex) 
          { 
           Logger.Info("could not save " + destinationFilePath+ " b/c: " + ex.Message); 
          } 
         } 
        } 
        catch (Exception ex) 
        { 
         Logger.Info("could not read " + fileName + " b/c: " + ex.Message); 
        } 
       } 
       catch (Exception ex) 
       { 
        Logger.Info("could not open download stream for " + fileName + " b/c: " + ex.Message); 
       } 
       finally 
       { 
        downloadResponse.Close(); 
       } 
      } 
      catch (Exception ex) 
      { 
       Logger.Info("could not get ftp response stream for " + fileName + " b/c: " + ex.Message); 
      } 
     } 
     catch (Exception ex) 
     { 
      Logger.Info("could not get ftp request stream for " + fileName + " b/c: " + ex.Message); 
     } 
    } 

Cela va dans le cadre d'un service continu, donc je ne veux pas jeter des erreurs qui arrêteraient le service. Au lieu de cela, j'écris à un journal. Voici le contenu du journal pour cette méthode:

2009-10-07 16:33:29.1421|INFO|xxx.Web.Controllers.FtpController|starting to download file: 2009-10-06155728Z_metadata.txt 
2009-10-07 16:33:29.1421|INFO|xxx.Web.Controllers.FtpController|getting ftp response for download file for 2009-10-06155728Z_metadata.txt 
2009-10-07 16:33:29.6661|INFO|xxx.Web.Controllers.FtpController|getting ftp response stream for 2009-10-06155728Z_metadata.txt 
2009-10-07 16:33:29.6661|INFO|xxx.Web.Controllers.FtpController|File Download status: 125 Data connection already open; Transfer starting. 
2009-10-07 16:33:29.6721|INFO|xxx.Web.Controllers.FtpController|getting binary reader for 2009-10-06155728Z_metadata.txt 
2009-10-07 16:33:29.6721|INFO|xxx.Web.Controllers.FtpController|writing response stream to C:\\Resumes\\2009-10-06155728Z_metadata.txt 
2009-10-07 16:33:29.6951|INFO|xxx.Web.Controllers.FtpController|could not save C:\\Resumes\\2009-10-06155728Z_metadata.txt b/c: This stream does not support seek operations. 

Je travaille sur cette voie trop longtemps, de sorte que toute aide serait appréciée!

Merci!

Répondre

8

Vous ne devez pas compter sur Stream.Length, il est possible que ce soit incorrect. Vous avez juste besoin de lire tous les octets dans une boucle while jusqu'à ce qu'il n'y ait plus d'octets à lire.

MemoryStream ms = new MemoryStream(); 
byte[] chunk = new byte[4096]; 
int bytesRead; 
while ((bytesRead = downloadStream.Read(chunk, 0, chunk.Length)) > 0) 
{ 
    ms.Write(chunk, 0, bytesRead); 
} 

À partir de là, toutes les données de lecture est dans le MemoryStream, et vous pouvez initialiser le BinaryReader avec cela.

+0

merci beaucoup pour la réponse rapide! –

+0

Si la réponse vous a aidé à résoudre votre problème, vous devez marquer la réponse comme acceptée. – mgbowen

1

La réponse de Darkassassin fonctionne très bien! Voici le code que j'ai finalement eu à travailler avant de voir son message. C'est légèrement différent car il écrit directement dans le fichier plutôt que dans le flux de mémoire.

Je remplacé cette ligne:

downloadWriter.Write(downloadReader.ReadBytes((int)downloadStream.Length)); 

avec ceci:

var buffer = new byte[BufferSize]; 
int readCount = downloadStream.Read(buffer, 0, BufferSize); 
while (readCount > 0) 
{ 
    downloadWriter.Write(buffer, 0, readCount); 
    readCount = downloadStream.Read(buffer, 0, BufferSize); 
} 

(BufferSize = 4096)

Merci encore pour l'aide rapide !!