I get a timeout error when using FtpWebRequest with SSL - c#

I have to upload some files on a FTP who use TLS with my C# application ( .net 3.5 )
With Filezila, no problems.
Now, with my C# code, i have a timeout exception and i really don't know why because all is ok with Filezila.
Here is my code :
public static bool AcceptAllCertificatePolicy(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return true;
}
public static string Upload_SSL(string filenameSrc)
{
ServicePointManager.ServerCertificateValidationCallback = AcceptAllCertificatePolicy;
FileInfo fileInfSrc = new FileInfo(filenameSrc);
FtpWebRequest reqFTP;
// Create FtpWebRequest object from the Uri provided
if (strDirectory.Trim() != "")
{
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + strHost.Trim() + "/" + strDirectory.Trim() + "/" + fileInfSrc.Name.Trim()));
}
else
{
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + strHost.Trim() + "/" + fileInfSrc.Name.Trim()));
}
reqFTP.EnableSsl = true;
// Provide the WebPermission Credintials
reqFTP.Credentials = new NetworkCredential(strUser.Trim(), strPass.Trim());
reqFTP.Proxy = null;
// By default KeepAlive is true, where the control connection is not closed
// after a command is executed.
reqFTP.KeepAlive = false;
// Specify the command to be executed.
reqFTP.Method = WebRequestMethods.Ftp.UploadFile;
// Specify the data transfer type.
reqFTP.UseBinary = true;
// Notify the server about the size of the uploaded file
reqFTP.ContentLength = fileInfSrc.Length;
// The buffer size is set to 8kb
int buffLength = 8192;
byte[] buff = new byte[buffLength];
int contentLen;
// Opens a file stream (System.IO.FileStream) to read the file to be uploaded
FileStream fs = fileInfSrc.OpenRead();
try
{
// Stream to which the file to be upload is written
Stream strm = reqFTP.GetRequestStream();
// Read from the file stream 2kb at a time
contentLen = fs.Read(buff, 0, buffLength);
// Till Stream content ends
while (contentLen != 0)
{
// Write Content from the file stream to the FTP Upload Stream
strm.Write(buff, 0, contentLen);
contentLen = fs.Read(buff, 0, buffLength);
}
// Close the file stream and the Request Stream
strm.Close();
fs.Close();
}
catch (Exception ex)
{
fs.Close();
return (ex.Message);
}
return "ok";
}
Now, the call :
myFtp.Class1.strHost = "ftp://XXXXXXXXXXXXX";
myFtp.Class1.strPass = "*****************";
myFtp.Class1.strUser = "*********";
myFtp.Class1.nPort = 21;
myFtp.Class1.Upload_SSL(#"D:\Test.txt");
As information, if i try to use my code in order to upload a file on a NON TLS/SLL server, all is ok. So the problem appear to be only for the TLS/SSL ftp.
Anyone have some ideas please ?
Thanks a lot,

I kept the FTP:// in the host, so the url was FTP://FTP:/xxxxx

Related

The underlying connection was closed The server committed a protocol violation c#

While executing the below code I am getting the following error
(The underlying connection was closed The server committed a protocol
violation )
. Please help on this. I almost go throw every article about the error still not getting the solution.
Thanks in Advance.
private static void Upload()
{
string sourceFile = System.IO.Path.Combine(filepath, filename);
string ftpServerIP = "Hostname";
string ftpUserID = "UserName";
string ftpPassword = "Password";
FileInfo fileInf = new FileInfo(sourceFile);
string uri = "ftp://" + ftpServerIP + "/" + fileInf.Name;
FtpWebRequest reqFTP;
// Create FtpWebRequest object from the Uri provided
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + ftpServerIP + "/" + fileInf.Name));
// Provide the WebPermission Credintials
reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
// By default KeepAlive is true, where the control connection is not closed
// after a command is executed.
reqFTP.KeepAlive = false;
// Specify the command to be executed.
reqFTP.Method = WebRequestMethods.Ftp.UploadFile;
// Specify the data transfer type.
reqFTP.UseBinary = true;
// Notify the server about the size of the uploaded file
reqFTP.ContentLength = fileInf.Length;
// The buffer size is set to 2kb
int buffLength = 2048;
byte[] buff = new byte[buffLength];
int contentLen;
// Opens a file stream (System.IO.FileStream) to read the file to be uploaded
FileStream fs = fileInf.OpenRead();
//try
//{
// Stream to which the file to be upload is written
Stream strm = reqFTP.GetRequestStream();
// Read from the file stream 2kb at a time
contentLen = fs.Read(buff, 0, buffLength);
// Until Stream content ends
while (contentLen != 0)
{
// Write Content from the file stream to the FTP Upload Stream
strm.Write(buff, 0, contentLen);
contentLen = fs.Read(buff, 0, buffLength);
}
// Close the file stream and the Request Stream
strm.Close();
fs.Close();
//}
//catch (Exception ex)
//{
// Console.Write(ex.Message, "Upload Error");
//}
}
I found the answer for the problem. I was using SFTP server instead of FTP the code was entirely different.
So I changed the code.
using Renci.SshNet;
public static void UploadSFTPFile()
{
_SftpDetails = ReadIniFile(IniFilePath, "Sftp_Settings", SftpDetails);
string sourcefile = System.IO.Path.Combine(filepath, filename);
string destinationpath = _SftpDetails["SftpDestinationFolder"];
string host = _SftpDetails["Host"];
string username = _SftpDetails["UserName"];
string password = _SftpDetails["Password"];
int port = Convert.ToInt32(_SftpDetails["Port"]); //Port 22 is defaulted for SFTP upload
try
{
using (SftpClient client = new SftpClient(host, port, username, password))
{
client.Connect();
client.ChangeDirectory(destinationpath);
using (FileStream fs = new FileStream(sourcefile, FileMode.Open))
{
client.BufferSize = 4 * 1024;
client.UploadFile(fs, Path.GetFileName(sourcefile));
}
}
}
catch(Exception ex)
{
Console.Write(ex.Message);
return;
}
}
you have to install .sshNet from the NuGet Package Manager

Sending multiple files over a single FTP connection

I am trying to modify this FTP connection method to upload multiple files in a single connection.
As you can see I have got a while loop that iterates through a filename and filepath array, I have set the WebRequest to keep alive. I am not sure what I should move out of the loop to stop new connections from constantly opening up.
This is the error I am getting:
The remote server returned an error: (550) File unavailable (e.g., file not found, no access).
Thanks in advance!
Public string FTPUploadMultipleFiles(string ftpURL, string Username, string Password, string[] filePaths, string[] fileNames)
{
string result = "OK";
try
{
int Counter = 0;
if (filePaths.Count() == fileNames.Count())
while (Counter <= filePaths.Count() - 1)
{
FileInfo fileInf = new FileInfo(filePaths[Counter]);
FtpWebRequest reqFTP;
// Create FtpWebRequest object from the Uri provided
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURL + "/" + fileNames[Counter]));
reqFTP.Credentials = new NetworkCredential(Username, Password);
reqFTP.KeepAlive = true;
// Specify the command to be executed.
reqFTP.Method = WebRequestMethods.Ftp.UploadFile;
// Specify the data transfer type.
reqFTP.UsePassive = true;
reqFTP.UseBinary = true;
// Notify the server about the size of the uploaded file
reqFTP.ContentLength = fileInf.Length;
// The buffer size is set to 2kb
int buffLength = 204800;
byte[] buff = new byte[buffLength];
int contentLen;
// Opens a file stream (System.IO.FileStream) to read the file to be uploaded
FileStream fs = fileInf.OpenRead();
try
{
// Stream to which the file to be upload is written
Stream strm = reqFTP.GetRequestStream();
// Read from the file stream 2kb at a time
contentLen = fs.Read(buff, 0, Convert.ToInt32(buffLength));
// Till Stream content ends
while (contentLen != 0)
{
// Write Content from the file stream to the FTP Upload Stream
strm.Write(buff, 0, contentLen);
contentLen = fs.Read(buff, 0, buffLength);
}
// Close the file stream and the Request Stream
strm.Close();
fs.Close();
Counter++;
}
catch (Exception ex)
{
result = ex.Message;
}
}
}
catch (Exception ex)
{
result = ex.Message;
}
return result;
}

upload a XML file using FTP in c#

Please tell me how to upload a XML file using FTP in c#? Im currently using FtpWebRequest method and its giving me errors
my code is
//Create FTP request
FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create("ftp://www.itsthe1.com/profiles/nuwan/sample.txt");
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential(Username, Password);
request.UsePassive = true;
request.UseBinary = true;
request.KeepAlive = false;
//Load the file
FileStream stream = File.OpenRead(#"C:\sample.txt");
byte[] buffer = new byte[stream.Length];
stream.Read(buffer, 0, buffer.Length);
stream.Close();
//Upload file
Stream reqStream = request.GetRequestStream();
reqStream.Write(buffer, 0, buffer.Length);
reqStream.Close();
Here is my successfully working code to upload any file through FTP (I've written it in VB.NET but hopefully you can convert it to C# using any of the online translators)
Public Function Upload(ByVal fi As FileInfo, Optional ByVal targetFilename As String = "") As Boolean
'copy the file specified to target file: target file can be full path or just filename (uses current dir)
'1. check target
Dim target As String
If targetFilename.Trim = "" Then
'Blank target: use source filename & current dir
target = GetCurrentUrl() & "/" & fi.Name
Else
'otherwise treat as filename only, use current directory
target = GetCurrentUrl() & "/" & targetFilename
End If
Dim URI As String = target 'GetCurrentUrl() & "/" & target
'perform copy
Dim ftp As Net.FtpWebRequest = GetRequest(URI)
'Set request to upload a file in binary
ftp.Method = Net.WebRequestMethods.Ftp.UploadFile
ftp.UseBinary = True
'Notify FTP of the expected size
ftp.ContentLength = fi.Length
'create byte array to store: ensure at least 1 byte!
Const BufferSize As Integer = 2048
Dim content(BufferSize - 1) As Byte, dataRead As Integer
'open file for reading
Using fs As FileStream = fi.OpenRead()
Try
'open request to send
Using rs As Stream = ftp.GetRequestStream
Dim totBytes As Long = 0
Do
dataRead = fs.Read(content, 0, BufferSize)
rs.Write(content, 0, dataRead)
totBytes += dataRead
RaiseEvent StatusChanged(totBytes.ToString() & " bytes sent...")
Loop Until dataRead < BufferSize
rs.Close()
RaiseEvent StatusChanged("File uploaded successfully")
End Using
Catch ex As Exception
RaiseEvent StatusChanged("Error: " & ex.Message)
Finally
'ensure file closed
fs.Close()
End Try
End Using
ftp = Nothing
Return True
End Function
Here is the link to the entire article about developing this FTP Client:
http://dot-net-talk.blogspot.com/2008/12/how-to-create-ftp-client-in-vbnet.html
protected void Button1_Click(object sender, EventArgs e)
{
string server = "-------"; //your ip address
string ftpPath = "ftp://" + server + "//Files//" +FileUpload1.FileName;
string uname = "-----";
string password = "----------";
string filePath = Server.MapPath("~") + "\\" + FileUpload1.FileName;
try
{
UploadToFTP(ftpPath,filePath,uname,password);
}
catch (Exception ex)
{
//logic here
}
}
`private bool UploadToFTP(string strFTPFilePath, string strLocalFilePath, string strUserName, string strPassword)
{
try
{
//Create a FTP Request Object and Specfiy a Complete Path
// System.Net.WebRequest.Create(strFTPFilePath);
FtpWebRequest reqObj = (FtpWebRequest)WebRequest.Create(strFTPFilePath);
//Call A FileUpload Method of FTP Request Object
reqObj.Method = WebRequestMethods.Ftp.UploadFile;
//If you want to access Resourse Protected,give UserName and PWD
reqObj.Credentials = new NetworkCredential(strUserName, strPassword);
// Copy the contents of the file to the byte array.
byte[] fileContents = File.ReadAllBytes(strLocalFilePath);
reqObj.ContentLength = fileContents.Length;
//Upload File to FTPServer
Stream requestStream = reqObj.GetRequestStream();
// Stream requestStream = response.GetResponseStream();
requestStream.Write(fileContents, 0, fileContents.Length);
requestStream.Close();
FtpWebResponse response = (FtpWebResponse)reqObj.GetResponse();
response.Close();
Label1.Text = "File Transfered Completed" + response.StatusDescription;
}
catch (Exception Ex)
{
throw Ex;
}
return true;
} `

FTP download / upload error 504

I'm trying to write a program which will download a few files from and FTP, zip them up then upload them again to the same FTP location.
I have got it to attempt to download a file. If it fails, it will try again.
If NO errors occur, all files download and upload file.
If any errors occur when downloading, it will download them on the re-attempt, but fail then to upload.
I think the problems are down to not correctly closing a connection, but I can't for the life of me figure it out.
Here's my code; I've added where it fails:
Upload:
FileInfo fileInf = new FileInfo("directory" + zip + ".zip");
string uri = "ftp://address" + fileInf.Name;
FtpWebRequest reqFTP2;
reqFTP2 = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://address" + fileInf.Name));
reqFTP2.Credentials = new NetworkCredential("username", "password");
reqFTP2.KeepAlive = true;
reqFTP2.Method = WebRequestMethods.Ftp.UploadFile;
reqFTP2.UseBinary = true;
reqFTP2.ContentLength = fileInf.Length;
int buffLength = 2048;
byte[] buff = new byte[buffLength];
int contentLen;
FileStream fs = fileInf.OpenRead();
try
{
Stream strm = reqFTP2.GetRequestStream(); //FAILS HERE
contentLen = fs.Read(buff, 0, buffLength);
while (contentLen != 0)
{
strm.Write(buff, 0, contentLen);
contentLen = fs.Read(buff, 0, buffLength);
}
strm.Close();
fs.Close();
}
catch (Exception ex)
{
}
Download:
int errorOccured = 0;
while (errorOccured < 1)
{
FileStream outputStream = new FileStream("directory\\" + file, FileMode.Create);
FtpWebRequest reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://address/" + file));
reqFTP.Credentials = new NetworkCredential("username", "password");
try
{
reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
reqFTP.UseBinary = true;
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
Stream ftpStream = response.GetResponseStream();
long cl = response.ContentLength;
int bufferSize = 2048;
int readCount;
byte[] buffer = new byte[bufferSize];
readCount = ftpStream.Read(buffer, 0, bufferSize);
while (readCount > 0)
{
outputStream.Write(buffer, 0, readCount);
readCount = ftpStream.Read(buffer, 0, bufferSize);
}
ftpStream.Close();
outputStream.Close();
response.Close();
errorOccured++;
}
catch (Exception er)
{
outputStream.Close();
}
The error 504 – Command not implemented for that parameter.
implies that some option you are using in there is not implemented by the target FTP server. I think that your code is resulting in a bizarre request, suggestion would be to look at the FTP chatter that your process creates on the server side. For exmaple, does the server support PASV mode? FTP protocol in ACTV mode (the default behavior) is always a pain because it explicitly causes the client to open a "file receive port" on port 20 and listen. While most servers support PASV mode transfers, it can become a pain if you don't put them in the PASV mode explicitly. So look at the chatter, see if the server is in PASV mode, and if you still have trouble, look at the chatter to see if there are "Extra Spaces" passed on during FTP negotiation. FTP is quite dinky and there can be several pitfalls. :-)
For starters, wrap your streams in using blocks so that they are disposed appropriately.
See MSDN for more details.

c# Uploading files to ftp server

I have a problem with uploading files to ftp server. I have a few buttons. Every button uploads different files to the ftp. The first time when a button is clicked the file is uploaded successfully, but the second and later tries fail. It gives me "The operation has timed out". When I close the site and then open it again I can upload again only one file. I am sure that I can override files on the ftp. Here's the code:
protected void btn_export_OnClick(object sender, EventArgs e)
{
Stream stream = new MemoryStream();
stream.Position = 0;
// fill the stream
bool res = this.UploadFile(stream, "test.csv", "dir");
stream.Close();
}
private bool UploadFile(Stream stream, string filename, string ftp_dir)
{
stream.Seek(0, SeekOrigin.Begin);
string uri = String.Format("ftp://{0}/{1}/{2}", "host", ftp_dir, filename);
try
{
FtpWebRequest reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
reqFTP.Credentials = new NetworkCredential("user", "pass");
reqFTP.Method = WebRequestMethods.Ftp.UploadFile;
reqFTP.KeepAlive = false;
reqFTP.UseBinary = true;
reqFTP.UsePassive = true;
reqFTP.ContentLength = stream.Length;
reqFTP.EnableSsl = true; // it's FTPES type of ftp
int buffLen = 2048;
byte[] buff = new byte[buffLen];
int contentLen;
try
{
Stream ftpStream = reqFTP.GetRequestStream();
contentLen = stream.Read(buff, 0, buffLen);
while (contentLen != 0)
{
ftpStream.Write(buff, 0, contentLen);
contentLen = stream.Read(buff, 0, buffLen);
}
ftpStream.Flush();
ftpStream.Close();
}
catch (Exception exc)
{
this.lbl_error.Text = "Error:<br />" + exc.Message;
this.lbl_error.Visible = true;
return false;
}
}
catch (Exception exc)
{
this.lbl_error.Text = "Error:<br />" + exc.Message;
this.lbl_error.Visible = true;
return false;
}
return true;
}
Does anyone have idea what may cause this strange behaviour? I think I'm closing all streams accurately. Could this be related with the ftp server settings? The admin said that the ftp handshake never happened second time.
start with wrapping your Stream creation in a using clause.
using(Stream stream = new MemoryStream())
{
stream.Position = 0;
// fill the stream
bool res = this.UploadFile(stream, "test.csv", "dir");
}
This will make sure that the stream is closed and that any unmanaged resources are disposed, whether an error occurs or not
I used your code, had the same problem, and fixed it.
After you close the stream, you have to read reqFTP response by calling GetResponse() then close the response. Here is the code that fixes the problem:
// Original code
ftpStream.Flush();
ftpStream.Close();
// Here is the missing part that you have to add to fix the problem
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
this.lbl_error.Text = "Response:<br />" + response.StatusDescription;
response.Close();
reqFTP = null;
this.lbl_error.Visible = true;
You don't have to display the response, you can just get it and close it, I am displaying it just for reference.

Categories

Resources