Sending multiple files over a single FTP connection - c#

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;
}

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

I get a timeout error when using FtpWebRequest with SSL

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

C# FtpWebRequest creates corrupted files

I'm using .NET 3.5 and I need to transfer by FTP some files.
I don't want to use files because I manage all by using MemoryStream and bytes arrays.
Reading these articles (article and article), I made my client.
public void Upload(byte[] fileBytes, string remoteFile)
{
try
{
string uri = string.Format("{0}:{1}/{2}", Hostname, Port, remoteFile);
FtpWebRequest ftp = (FtpWebRequest)WebRequest.Create(uri);
ftp.Credentials = new NetworkCredential(Username.Normalize(), Password.Normalize());
ftp.UseBinary = true;
ftp.UsePassive = true;
ftp.Method = WebRequestMethods.Ftp.UploadFile;
using (Stream localFileStream = new MemoryStream(fileBytes))
{
using (Stream ftpStream = ftp.GetRequestStream())
{
int bufferSize = (int)Math.Min(localFileStream.Length, 2048);
byte[] buffer = new byte[bufferSize];
int bytesSent = -1;
while (bytesSent != 0)
{
bytesSent = localFileStream.Read(buffer, 0, bufferSize);
ftpStream.Write(buffer, 0, bufferSize);
}
}
}
}
catch (Exception ex)
{
LogHelper.WriteLog(logs, "Errore Upload", ex);
throw;
}
}
The FTP client connects, writes and close correctly without any error. But the written files are corrupted, such as PDF cannot be opened and for DOC/DOCX Word shows a message about file corruption and tries to restore them.
If I write to a file the same bytes passed to the Upload method, I get a correct file. So the problem must be with FTP transfer.
byte[] fileBytes = memoryStream.ToArray();
File.WriteAllBytes(#"C:\test.pdf", fileBytes); // --> File OK!
ftpClient.Upload(fileBytes, remoteFile); // --> File CORRUPTED on FTP folder!
You need to use bytesSent in the Write call:
bytesSent = localFileStream.Read(buffer, 0, bufferSize);
ftpStream.Write(buffer, 0, bytesSent);
Otherwise you write too many bytes in the last round.

Multiple threads uploading files to filezilla ftp server returns error 550 File unavailable

Problem: When i ftp upload only one file at a time, the files are uploaded fine, But when i use multiple Background workers to upload files to ftp server i get exception:
ex {"The remote server returned an error: (550) File unavailable
(e.g., file not found, no access)."} System.Exception
{System.Net.WebException}
And only Some of the files get uploaded. I am pretty sure the file exits at that location, infact in another run the file it was complaining about that does not exist is downloaded but the error shifts on another file.
Code Description:
In below code i am downloading a file from one ftp server and putting it on another. This code is inside a BackgroundsWorker_DoWork Method. Background Workers are being created inside a loop.
void imageDownloadWorker_DoWork(object sender, DoWorkEventArgs e)
{
string[] ftpInfo = (string[])e.Argument;
try
{
///////////////////////////Downloading///////////////////////////////////////
string uri = String.Format("ftp://{0}/{1}/images/{2}", ftpInfo[1], ftpInfo[2], ftpInfo[5]);
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(uri);
request.Method = WebRequestMethods.Ftp.DownloadFile;
request.UseBinary = true;
request.Credentials = new NetworkCredential(ftpInfo[3], ftpInfo[4]);
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
Stream ftpStream = response.GetResponseStream();
long cl = response.ContentLength;
int bufferSize = 4096;
int readCount = 0;
byte[] buffer = new byte[bufferSize];
MemoryStream memStream = new MemoryStream();
readCount = ftpStream.Read(buffer, 0, bufferSize);
while (readCount > 0)
{
memStream.Write(buffer, 0, readCount);
readCount = ftpStream.Read(buffer, 0, bufferSize);
}
response.Close();
///////////////////////////Uploading///////////////////////////////////////
string uri1 = String.Format("ftp://{0}/{1}/{2}", "127.0.0.1", string.Empty, ftpInfo[5]);
FtpWebRequest request1 = (FtpWebRequest)WebRequest.Create(uri1);
request1.Credentials = new NetworkCredential("user", "password");
request1.KeepAlive = false;
request1.Method = WebRequestMethods.Ftp.UploadFile;
request1.UseBinary = true;
request1.ContentLength = memStream.Length;
int buffLength = 4096;
byte[] buff = new byte[buffLength];
int contentLen;
// Stream to which the file to be upload is written
Stream strm = request1.GetRequestStream();
memStream.Seek(0, SeekOrigin.Begin);
contentLen = memStream.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 = memStream.Read(buff, 0, buffLength);
}
// Close the file stream and the Request Stream
strm.Close();
ftpStream.Close();
memStream.Close();
}
catch(Exception ex)
{
MessageBox.Show("While Downloading File " + ftpInfo[5] + " " + ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
e.Result = null;
return;
}
Related Thread
Edit:
In File Zilla Server there is an option General Settings>Perfomance Settings>Number of Threads i have set that to 20 it didnt make any difference.
There maybe nothing wrong with your code. That error is a Permissions error.
Complete stab in the dark, but does the upload target server have a connection per IP limit? If so you may be falling foul of this by exceeding the concurrent connection limit from a single IP address.

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