Reputation: 25
try
{
FtpWebRequest req = (FtpWebRequest)WebRequest.Create("ftp path");
req.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
using (var resp = (FtpWebResponse)req.GetResponse())
{
Console.WriteLine(resp.WelcomeMessage);
}
FtpWebResponse res = (FtpWebResponse)req.GetResponse();
Stream rs = res.GetResponseStream();
StreamReader read1 = new StreamReader(res.GetResponseStream());// prob A
Console.WriteLine(read1.ReadToEnd());
Console.WriteLine("Directory is compleate,status(0)",
res.StatusDescription);
read1.Close();
rs.Close();
}
catch (Exception e1)
{
Console.WriteLine(e1.Message);
}
I am trying to access ftp server via C#.
However, the code errors with an exception:
A first chance exception of type "System.ArgumentException" occured in mscorlib.dll. Stream was not readable.
Any help will be appreciated.
Upvotes: 2
Views: 17357
Reputation: 2487
TLDR; The state of the FtpWebResponse
object is disposed, therefore you cannot read the response stream. The stream is closed.
Disassembly of FtpWebResponse:
public override void Close()
{
if (Logging.On)
{
Logging.Enter(Logging.Web, this, "Close", "");
}
if (this.HttpProxyMode)
{
this.m_HttpWebResponse.Close();
}
else
{
Stream responseStream = this.m_ResponseStream;
if (responseStream != null)
{
responseStream.Close();
}
}
if (Logging.On)
{
Logging.Exit(Logging.Web, this, "Close", "");
}
}
The reason you get the exception, is that you are reading the response:
using (var resp = (FtpWebResponse)req.GetResponse())
{
Console.WriteLine(resp.WelcomeMessage);
}
and on the next line, you try to read the response again, into another variable: res
FtpWebResponse res = (FtpWebResponse)req.GetResponse();
Stream rs = res.GetResponseStream();
StreamReader read1 = new StreamReader(res.GetResponseStream());// prob A
In that section, you also do a call to the res.GetResponseStream()
twice, but that does not matter in terms of the error occuring. The error will occur even if you change it to:
FtpWebResponse res = (FtpWebResponse)req.GetResponse();
Stream rs = res.GetResponseStream();
StreamReader read1 = new StreamReader(rs);// prob A
Or:
FtpWebResponse res = (FtpWebResponse)req.GetResponse();
StreamReader read1 = new StreamReader(res.GetResponseStream());// prob A
The reason that the error occurs, is the state of the FtpWebResponse
object, which is disposed; and has the StatusCode = ClosingData
. When I try to read the stream in that state, I get the error you are experiencing. In the using block before, the StatusCode = OpeningData
.
However, if you just change a couple of lines to:
using (var resp = (FtpWebResponse)req.GetResponse())
{
Console.WriteLine(resp.WelcomeMessage);
Stream rs = res.GetResponseStream();
StreamReader read1 = new StreamReader(rs);// prob A
Console.WriteLine(read1.ReadToEnd());
Console.WriteLine("Directory is compleate,status(0)", res.StatusDescription);
}
When entering this using scope, the StatusCode = OpeningData
, and stream is available and readable. When exiting the scope, the StatusCode = ClosingData
, and stream will not be readable.
Hope this make some sense, and correct me if I'm wrong. :-)
With these small changes your code will run as expected. However you should look into the pattern @DmitryBychenko proposes. That way you will have access to the resources within the scope that they're needed, and disposed afterwards.
Upvotes: 0
Reputation: 186803
Put all IDisposable
resources within using(...) {...}
. That technics prevents
resource leaking/closed resources invoking:
try {
FtpWebRequest req = (FtpWebRequest)WebRequest.Create("ftp path");
req.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
// Response: we're going to work wuth respose within "using" block only
using (FtpWebResponse resp = (FtpWebResponse)req.GetResponse()) {
Console.WriteLine(resp.WelcomeMessage);
// Reader: once again reader's opened once and called within using only
using (StreamReader reader = new StreamReader(resp.GetResponseStream())) {
Console.WriteLine(reader.ReadToEnd());
Console.WriteLine("Directory is complete, status(0)", resp.StatusDescription);
}
}
catch (Exception ex) { // <- Bad idea to catch all possible exceptions without "throw;"
Console.WriteLine(ex.Message);
}
Upvotes: 2