Problem with FtpWebRequest and SSL
Hi,
I have an annoying problem with a FTP upload. I want to upload a few files to a FTP Server. This FTP Server is an IIS FTP 7.5 server with required SSL and basic authentication.
I wrote the code below and all works fine on my local development computer. But if I try to run the code against a remote FTP server the first call works fine, but always the second one fails with the following error: "Authentication failed because the remote party has closed the transport stream."
I tried so much but nothing works for me. Any suggestions?
Code:
internal class FtpAsynchronous
{
/// <summary>
/// Asynchronouses the upload.
/// </summary>
/// <param name="baseUrl">The base URL.</param>
/// <param name="filename">The filename.</param>
/// <param name="state">The state.</param>
internal void AsynchronousUpload(Uri baseUrl, string filename, FtpState state)
{
Uri url = baseUrl;
// if a filename is available use it a relative url
if (!String.IsNullOrEmpty(filename))
{
url = new Uri(baseUrl, filename);
}
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(url);
// we want to upload a file
request.Method = WebRequestMethods.Ftp.UploadFile;
// enable SSL
request.EnableSsl = true;
// do not reuse connection
request.KeepAlive = false;
// set ftp credentials
request.Credentials = new NetworkCredential(Settings.Default.FtpUsername, Settings.Default.FtpPassword);
// Store the request in the object that we pass into the
// asynchronous operations.
state.Request = request;
// Get the event to wait on.
ManualResetEvent waitObject = state.OperationComplete;
// Asynchronously get the stream for the file contents.
request.BeginGetRequestStream(EndGetStreamCallback, state);
// Block the current thread until all operations are complete.
waitObject.WaitOne();
// The operations either completed or threw an exception.
if (state.OperationException != null)
{
throw state.OperationException;
}
}
/// <summary>
/// Ends the get stream callback.
/// </summary>
/// <param name="ar">The ar.</param>
private static void EndGetStreamCallback(IAsyncResult ar)
{
FtpState state = (FtpState)ar.AsyncState;
// End the asynchronous call to get the request stream.
try
{
state.Request.ContentLength = state.Content.Length;
Stream requestStream = state.Request.EndGetRequestStream(ar);
requestStream.Write(state.Content, 0, state.Content.Length);
// IMPORTANT: Close the request stream before sending the request.
requestStream.Close();
// Asynchronously get the response to the upload request.
state.Request.BeginGetResponse(EndGetResponseCallback, state);
}
catch (Exception e)
{
// Return exceptions to the main application thread.
state.OperationException = e;
state.OperationComplete.Set();
}
}
/// <summary>
/// Ends the get response callback.
/// </summary>
/// <param name="ar">The ar.</param>
private static void EndGetResponseCallback(IAsyncResult ar)
{
FtpState state = (FtpState)ar.AsyncState;
try
{
FtpWebResponse response = (FtpWebResponse)state.Request.EndGetResponse(ar);
response.Close();
state.StatusDescription = response.StatusDescription;
// Signal the main application thread that
// the operation is complete.
state.OperationComplete.Set();
}
catch (Exception e)
{
// Return exceptions to the main application thread.
state.OperationException = e;
state.OperationComplete.Set();
}
}
public class FtpState
{
/// <summary>
/// thread notifier
/// </summary>
private readonly ManualResetEvent wait;
/// <summary>
/// Initializes a new instance of the <see cref="FtpState"/> class.
/// </summary>
public FtpState()
{
this.OperationException = null;
this.wait = new ManualResetEvent(false);
}
/// <summary>
/// Gets the operation complete.
/// </summary>
/// <value>The operation complete.</value>
public ManualResetEvent OperationComplete
{
get { return this.wait; }
}
/// <summary>
/// Gets or sets the request.
/// </summary>
/// <value>The request.</value>
public FtpWebRequest Request { get; set; }
/// <summary>
/// Gets or sets the name of the file.
/// </summary>
/// <value>The name of the file.</value>
public string FileName { get; set; }
/// <summary>
/// Gets or sets the operation exception.
/// </summary>
/// <value>The operation exception.</value>
public Exception OperationException { get; set; }
/// <summary>
/// Gets or sets the status description.
/// </summary>
/// <value>The status description.</value>
public string StatusDescription { get; set; }
/// <summary>
/// Gets or sets the content.
/// </summary>
/// <value>The content.</value>
internal byte[] Content { get; set; }
}
Thats the basics and here comes the final call:
Code:
foreach (var document in documents)
{
FtpAsynchronous ftp = new FtpAsynchronous();
ftp.AsynchronousUpload(new Uri(Settings.Default.FtpBaseUrl), document.FtpFilename, new FtpState { FileName = document.Name, Content = document.Content });
}
I believe there is a problem with the SSL on the IIS FTP 7.5 but I can not find anything. So maybe I made a mistake in the code.
Re: Problem with FtpWebRequest and SSL
There seems to be quite a bit of info by searching bing or google for "Authentication failed because the remote party has closed the transport stream".
Have you tried looking through these responses?