2009-10-07 224 views
3

我想从使用C#和ftpwebrequest的ftp服务器下载文件。我可以使用BinaryReader获取字节,但是当我尝试使用br.ReadBytes(int)读取流时,出现BinaryReader不支持查找操作的错误。C#BinaryReader“流不支持查找操作”

有谁知道如何最好地读取字节,以便我可以将它们写入文件?

下面是完整的方法:

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); 
     } 
    } 

这将运行作为一个持续服务的一部分,所以我不希望引发错误,将停止该服务。相反,我正在写日志。这里是这种方法的日志内容:

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. 

我一直在这方面工作太久,所以任何帮助将不胜感激!

谢谢!

回答

8

你不应该依赖于Stream.Length,它可能是错的。您只需要在while循环中读取所有字节,直到没有更多的字节可读。

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); 
} 

从那里,所有的读取的数据是在MemoryStream,你可以初始化BinaryReader这一点。

+0

非常感谢您的快速响应! – 2009-10-08 00:30:07

+0

如果答案帮助你解决了问题,你应该将答案标记为已接受。 – mgbowen 2009-10-08 00:34:56

1

Darkassassin的回答很好!这是我在看到他的帖子之前终于开始工作的代码。它与直接写入文件而不是内存流的B/C略有不同。再次

感谢

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); 
} 

(缓冲区大小= 4096)的快速帮助!!:

我换成这一行:

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

与此