Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 重用FtpWebRequest_C#_.net_Ftp_Ftpwebrequest - Fatal编程技术网

C# 重用FtpWebRequest

C# 重用FtpWebRequest,c#,.net,ftp,ftpwebrequest,C#,.net,Ftp,Ftpwebrequest,我正在尝试使用ftpWebRequestMethods.FTP.DownloadFile方法从FTP下载文件。问题是,我不想显示下载的进度,因此需要提前知道文件大小,以便能够计算传输的百分比。但是当我在FtpWebRequest中调用GetResponse时,ContentLength成员是-1 好的-因此我使用方法WebRequestMethods.Ftp.GetFileSize预先获得文件的大小。没问题。然后在得到大小后,我下载文件 这就是问题所在 得到大小后,我尝试重用FtpWebRequ

我正在尝试使用
ftpWebRequestMethods.FTP.DownloadFile
方法从FTP下载文件。问题是,我不想显示下载的进度,因此需要提前知道文件大小,以便能够计算传输的百分比。但是当我在
FtpWebRequest
中调用
GetResponse
时,
ContentLength
成员是-1

好的-因此我使用方法
WebRequestMethods.Ftp.GetFileSize
预先获得文件的大小。没问题。然后在得到大小后,我下载文件

这就是问题所在

得到大小后,我尝试重用
FtpWebRequest
,并将该方法重置为
WebRequestMethods.Ftp.DownloadFile
。这会导致出现一个
System.invalidoOperationException
语句,如“发送请求后无法执行此操作”。(可能不是确切的表述-翻译自我在瑞典语中得到的表述)

我在其他地方发现,只要我将
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
现在我得到了文件大小。现在是下载文件的时候了。设置方法现在导致上述异常。那么我是否要创建一个新的
FtpWebRequest
?或者是否有任何方法重置要重用的请求?(关闭响应没有任何区别。)

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

以下是(非工作)代码(输入为sURI、sDiskName、sUser和sPwd):


我希望有人能解释一下这是怎么回事。提前感谢。

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

这将防止您的应用程序也被锁定,因此您不必使用

Application.DoEvents();
您还可以考虑使用另一个ftp库。在我看来,FtpWebRequest并不是最好的ftp类。快速搜索找到了这个图书馆。Ftp不像HTTP那样是无状态的。我更喜欢创建客户端、打开连接并保持连接活动的库

这是我找到的代码示例

FtpClient client = 
    new FtpClient( 
        new IPEndPoint( IPAddress.Loopback, 21 ), 
        new NetworkCredential( "test", "testing@localdomain" ) 
    );
client.Connect();
client.Download("testfile.zip", @"C:\downloads\testfile.zip");

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

我认为这不会得到回答,因此我将通过告诉您我是如何解决的来“关闭它”

嗯,我并没有真正解决它。不过,我确实通过重新创建
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
以重新使用,则没有回答。但至少我知道没有多余的信息被传输


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

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


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

至少对于HTTPWebRequests,您必须始终创建一个新的连接。假设这里有同样的问题。
FtpWebRequest
适用于发出单个请求。您需要一个FTP客户端,它连接并保持一个持久连接,直到您关闭它
System.Net.FtpClient
似乎很受欢迎:在这种情况下,我有点不愿意使用第三方产品。我很清楚FTP的内部工作原理,因为我从头开始编写服务器和客户端库。我想知道的是,是否可以使用
FtpWebRequest
。如果不是,我想我会选择异步方法(我之前选择了异步方法,因为它增加了代码的复杂性)。但让事情复杂化有点遗憾,当我不是真正关注异步行为时,除了进度条更新。。。无论如何,谢谢。我只是想澄清一下,使用FtpWebRequest是否不可能在不登录10次的情况下发送10个文件?这个答案说明了这应该如何工作,所以基本上你做的是“正确的”事情。这一个展示了如何跟踪FTP请求,所以您可以看到请求之间的连接是真正重用的
FtpClient client = 
    new FtpClient( 
        new IPEndPoint( IPAddress.Loopback, 21 ), 
        new NetworkCredential( "test", "testing@localdomain" ) 
    );
client.Connect();
client.Download("testfile.zip", @"C:\downloads\testfile.zip");
// 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();