重用FtpWebRequest

Sam*_*han 9 .net c# ftp ftpwebrequest

我正在尝试使用FtpWebRequest该方法从FTP下载文件的简单方法WebRequestMethods.Ftp.DownloadFile.问题是我不想显示下载的进度,因此需要知道前面的文件大小才能计算转移的百分比.但是,当我打电话GetResponseFtpWebRequestContentLength成员为-1.

好的 - 所以我使用该方法预先获得文件的大小WebRequestMethods.Ftp.GetFileSize.没问题.在获得大小后我下载文件.

这就是问题出现的地方......

获得大小后我尝试重用FtpWebRequest并重置方法WebRequestMethods.Ftp.DownloadFile.这会导致System.InvalidOperationException类似"发送请求后无法执行此操作"之类的说法.(可能不是确切的表述 - 翻译自瑞典语).

我在其他地方发现,只要我将KeepAlive属性设置为true,无关紧要,连接保持活动状态.这是我不明白的......我创造的唯一对象是我的FtpWebRequest对象.如果我创建另一个,它怎么知道使用什么连接?什么凭据?

伪代码:

Create FtpWebRequest
Set Method property to GetFileSize
Set KeepAlive property to true
Set Credentials property to new NetworkCredential(...)
Get FtpWebResponse from the request
Read and store ContentLength
Run Code Online (Sandbox Code Playgroud)

现在我得到了文件大小.所以是时候下载文件了.设置方法知道导致上述异常.所以我创建一个新的FtpWebRequest?或者无论如何重置请求重用?(结束回复没有任何区别.)

我不明白如何在不重新创建对象的情况下前进.我能做到这一点,但感觉不对劲.所以我在这里发帖,希望能找到正确的方法.

这是(非工作)代码(输入是sURI,sDiskName,sUser和sPwd.):

FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(sURI);
request.Method = WebRequestMethods.Ftp.GetFileSize;
request.Credentials = new NetworkCredential(sUser, sPwd);
request.UseBinary = true;
request.UsePassive = true;
request.KeepAlive = true;

FtpWebResponse resp = (FtpWebResponse)request.GetResponse();
int contLen = (int)resp.ContentLength;
resp.Close();

request.Method = WebRequestMethods.Ftp.DownloadFile;

resp = (FtpWebResponse)request.GetResponse();

Stream inStr = resp.GetResponseStream();
byte[] buff = new byte[16384];

sDiskName = Environment.ExpandEnvironmentVariables(sDiskName);
FileStream file = File.Create(sDiskName);

int readBytesCount;
int readTotal=0;

while ((readBytesCount = inStr.Read(buff, 0, buff.Length)) > 0)
{
    readTotal += readBytesCount;
    toolStripProgressBar1.Value = 100*readTotal/contLen;
    Application.DoEvents();
    file.Write(buff, 0, readBytesCount);
}
file.Close();
Run Code Online (Sandbox Code Playgroud)

我希望有人可以解释这是如何工作的.提前致谢.

Sam*_*han 7

我不认为这会得到回答所以我通过告诉你我是如何解决它而"关闭它".

好吧,我没有真正解决它.然而,我确实通过重新创建测试下载,FtpWebRequest并注意到在FTP服务器上它表现得像我想要的那样,即只有一个登录然后顺序执行我的请求.

这就是代码获取文件大小并开始下载的方式:

// Start by fetching the file size
FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(sURI);

request.Method = WebRequestMethods.Ftp.GetFileSize;
NetworkCredential nc = new NetworkCredential(sUser, sPwd);
request.Credentials = nc;
request.UseBinary = true;
request.UsePassive = true;
request.KeepAlive = true;

// Get the result (size)
FtpWebResponse resp = (FtpWebResponse)request.GetResponse();
Int64 contLen = resp.ContentLength;

// and now download the file
request = (FtpWebRequest)FtpWebRequest.Create(sURI);
request.Method = WebRequestMethods.Ftp.DownloadFile;
request.Credentials = nc;
request.UseBinary = true;
request.UsePassive = true;
request.KeepAlive = true;

resp = (FtpWebResponse)request.GetResponse();
Run Code Online (Sandbox Code Playgroud)

因此,如果可以重置FtpWebRequest重复使用,则无法回答.但至少我知道没有多余的信息被转移.

感谢所有感兴趣并花时间思考答案的人.


Pet*_*ber 5

FtpWebRequest 只能用于 1 个请求,例如获取文件大小或下载文件,但不能同时用于两者。您必须创建 2 个 FtpWebRequests。在幕后,FtpWebRequest 注意到它是相同的 URL 和凭据,并且会重用相同的 ftp 连接而不关闭它,只要 IsKeepAlieve 为 true,这是默认设置。

这是微软糟糕设计的一个可悲的例子。他们不想让我们明确地打开和关闭连接,而是希望自动为我们做这件事,让每个人都感到困惑。