我试图用FtpWebRequest
和WebRequestMethods.Ftp.DownloadFile
方法创建一个从ftp下载文件的简单方法。问题是我不想显示下载的进度,因此需要知道前面的文件大小才能计算传输的百分比。但当我在GetResponse
中调用FtpWebRequest
时,ContentLength
成员是-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
现在我得到了文件大小。所以是时候下载文件了。设置方法know导致上述异常。那么我要创建一个新的
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();
我希望有人能解释一下这是怎么回事。提前谢谢。
最佳答案
我想这个问题不会有答案,所以我要告诉你我是如何解决的。
嗯,我并没有真正解决它。不过,我确实通过重新创建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();
因此,如果可以重置
FtpWebRequest
以重新使用,则无需回答。但至少我知道没有多余的信息被转移。感谢所有感兴趣并花时间思考答案的人。