首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >重用FtpWebRequest

重用FtpWebRequest
EN

Stack Overflow用户
提问于 2013-07-03 23:07:38
回答 3查看 7.2K关注 0票数 10

我正在尝试创建一个简单的方法,使用带有WebRequestMethods.Ftp.DownloadFile方法的FtpWebRequest从FTP下载文件。问题是我不想显示下载的进度,因此需要知道文件大小才能计算传输的百分比。但是当我在FtpWebRequest中调用GetResponse时,ContentLength成员是-1。

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

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

在获得大小之后,我尝试重用FtpWebRequest并重置该方法为WebRequestMethods.Ftp.DownloadFile。这会导致System.InvalidOperationException显示类似“发送请求后无法执行此操作”之类的信息。(可能不是确切的公式-从我用瑞典语得到的公式翻译过来)。

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

伪代码:

代码语言:javascript
复制
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

现在我得到了文件大小。现在是下载文件的时候了。设置方法现在会导致上述异常。那么我要创建一个新的FtpWebRequest吗?或者有没有什么方法可以重置请求以供重用?(关闭响应没有任何区别。)

我不知道如何在不重新创建对象的情况下继续前进。我可以这么做,但感觉就是不对劲。所以我在这里发帖,希望找到做这件事的正确方法。

下面是(不工作的)代码(输入为sURI、sDiskName、sUser和sPwd):

代码语言:javascript
复制
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();

我希望有人能解释一下这是如何工作的。提前谢谢。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-07-10 21:33:26

我认为这个问题不会得到回答,所以我将通过告诉你我是如何解决它的来“关闭它”。

嗯,我并没有真正解决它。然而,我确实通过重新创建FtpWebRequest来测试下载,并注意到它在FTP服务器上的行为与我想要的一样,即只登录一次,然后按顺序执行我的请求。

下面是获取文件大小并开始下载的代码的结果:

代码语言:javascript
复制
// 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以供重复使用,则没有答案。但至少我知道没有多余的信息被传输。

感谢关心并花时间思考答案的每一个人。

票数 7
EN

Stack Overflow用户

发布于 2013-08-07 10:47:19

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

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

票数 5
EN

Stack Overflow用户

发布于 2013-07-03 23:33:28

您可能会想要使用异步方法。这是指向MSDN文档的链接。

http://msdn.microsoft.com/en-us/library/system.net.ftpwebrequest.aspx

代码语言:javascript
复制
GetResponseAsync()

这也可以避免你的应用程序被锁定,所以你不需要使用

代码语言:javascript
复制
Application.DoEvents();

您还可以考虑使用替代的ftp库。FtpWebRequest并不是最好的ftp类。快速搜索一下就找到了这个库。Ftp不像HTTP那样是无状态的。我更喜欢让您创建客户端、打开连接并使连接保持活动状态的库。

http://sanity-free.org/dist/NullFX.Net-binary.zip

这是我找到的代码

代码语言:javascript
复制
FtpClient client = 
    new FtpClient( 
        new IPEndPoint( IPAddress.Loopback, 21 ), 
        new NetworkCredential( "test", "testing@localdomain" ) 
    );
client.Connect();
client.Download("testfile.zip", @"C:\downloads\testfile.zip");

源代码也在那里,所以您可能会将一些事件附加到读取过程中,以便跟踪下载进度。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17451620

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档