I am trying to download files from an ftp server using C# and ftpwebrequest. I can get the bytes using BinaryReader, but when I try to read the stream using br.ReadBytes(int), I get an error that BinaryReader does not support seek operations.
我正在尝试用c#和ftpwebrequest从一个ftp服务器下载文件。我可以使用BinaryReader来获取字节,但是当我尝试使用br.ReadBytes(int)读取流时,我得到一个错误,即BinaryReader不支持查找操作。
Does anyone know how best to read the bytes so I can write them to a file?
有没有人知道如何最好地读取字节,这样我就可以将它们写入文件?
Here's the full method:
这是完整的方法:
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);
}
}
This runs as part of an ongoing service, so I don't want to throw errors that would stop the service. Instead, I'm writing to a log. Here are the contents of the log for this method:
这是正在运行的服务的一部分,所以我不想抛出会停止服务的错误。相反,我在写日志。下面是该方法的日志内容:
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.
I've been working on this way too long, so any help would be appreciated!
我在这方面工作太久了,所以任何帮助都是值得感激的!
Thanks!!
谢谢! !
2 个解决方案
#1
8
You shouldn't rely on Stream.Length
, its possible it could be wrong. You just need to read all of the bytes in a while loop until there are no more bytes to read.
你不应该依赖于流。长度,可能是错的。您只需要在一个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);
}
From there, all the read data is in the MemoryStream
, and you can initialize the BinaryReader
with that.
从那里,所有读取数据都在MemoryStream中,您可以使用它初始化BinaryReader。
#2
1
Darkassassin's answer works great! Here's the code I finally got to work before I saw his post. It's slightly different b/c it writes directly to the file rather than to the memory stream.
Darkassassin回答的作品太棒了!在我看到他的帖子之前,我终于开始工作了。它是稍微不同的b/c,它直接写入文件而不是内存流。
I replaced this line:
我更换这条线:
downloadWriter.Write(downloadReader.ReadBytes((int)downloadStream.Length));
with this:
用这个:
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)
(BufferSize = 4096)
Thanks again for the quick help!!
再次感谢您的快速帮助!!
#1
8
You shouldn't rely on Stream.Length
, its possible it could be wrong. You just need to read all of the bytes in a while loop until there are no more bytes to read.
你不应该依赖于流。长度,可能是错的。您只需要在一个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);
}
From there, all the read data is in the MemoryStream
, and you can initialize the BinaryReader
with that.
从那里,所有读取数据都在MemoryStream中,您可以使用它初始化BinaryReader。
#2
1
Darkassassin's answer works great! Here's the code I finally got to work before I saw his post. It's slightly different b/c it writes directly to the file rather than to the memory stream.
Darkassassin回答的作品太棒了!在我看到他的帖子之前,我终于开始工作了。它是稍微不同的b/c,它直接写入文件而不是内存流。
I replaced this line:
我更换这条线:
downloadWriter.Write(downloadReader.ReadBytes((int)downloadStream.Length));
with this:
用这个:
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)
(BufferSize = 4096)
Thanks again for the quick help!!
再次感谢您的快速帮助!!