Uploading multiple files in .NET through FTP - c#

I am thinking of using following code, but I want to transfer hundreds of files and it does not look viable to connect and then disconnect on every file transfer.
request = (FtpWebRequest) FtpWebRequest.Create(FtpAddress + file);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential(User, Pass);
request.UsePassive = IsPassive;
request.UseBinary = true;
request.KeepAlive = false;
FileStream fs = File.OpenRead("");
byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);
fs.Close();
Stream ftpStream = request.GetRequestStream();
ftpStream.Write(buffer, 0, buffer.Length);
ftpStream.Close();
What options do I have for uploading all of these files using a single connection?

I have not verified this to be true, but in my quick 30 second search, if you set
request.KeepAlive = true;
on every request you create except the last one, apparently only the first FTPWebRequest makes a full login connection.
Then when you create the last FTPWebRequest, set
request.KeepAlive = false;
and it will close the connection when done. You can verify this if you have access to the FTP server's logs.

Related

C# download large file from FTP get hung

I have a FTP (Filezila server), and I would like to download a large file on it, using c#.
WebClient client = new WebClient();
client.Credentials = new NetworkCredential(userName, password);
client.DownloadFile(new Uri("ftp://XXX.XXX.XXX.XXX/" + fileName), destinationFileFullPath);
or
FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://XXX.XXX.XXX.XXX/" + fileName);
request.Method = WebRequestMethods.Ftp.DownloadFile;
request.KeepAlive = true; // I tried both
request.UseBinary = true; // I tried both
request.UsePassive = true;
request.Credentials = new NetworkCredential(userName, password);
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();
// Writing bytes to local files
using (var outputStream = File.OpenWrite(destinationFileFullPath))
{
byte[] chunk = new byte[2048];
int bytesRead;
do
{
bytesRead = responseStream.Read(chunk, 0, chunk.Length);
outputStream.Write(chunk, 0, bytesRead);
} while (bytesRead > 0);
outputStream.Flush();
}
responseStream.Close();
response.Close();
For small file, it works well, but for large file (by large I mean around ~300MB and more) it works, but at the end of the transfer (I see on filezilla server side that the transfer is a success) for an unknown reason my app just hang on the line
client.DownloadFile(new Uri("ftp://XXX.XXX.XXX.XXX/" + fileName), destinationFileFullPath);
or
bytesRead = responseStream.Read(chunk, 0, chunk.Length);
until I got a timeout exception. If I force the break (pause) I can see that is really stuck on this line. It is like if Filezilla close the connection and C# just wait more to read...
Did you already experienced this issue?
Thanks for your help.

Can't upload file to ftp in c#

can't upload file to ftp this is my code....
string filename = Path.GetFileName(source);
FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(ftp + ftpFolder + filename);
request.Credentials = new NetworkCredential("username", "password");
request.UseBinary = true;
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Proxy = new WebProxy();
FileStream fs = File.OpenRead(source);
byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);
fs.Close();
Stream ftpstream = request.GetRequestStream();
ftpstream.Write(buffer, 0, buffer.Length);
ftpstream.Close();
File.Delete(source);
always an error is occuring at GetRequestStream() the command is not recognized... how can I overcome this error ?
Any help will be appreciated....
add these two line
request.KeepAlive = false;
request.UsePassive= false;
then also if it is not working check whether your antivirus is blocking FTP

C# FTP Uload Acces denied Error 550

My Class FTP work fine wtih my FTP server, but not with my client FTP server.
public class UploadToFTP
{
public void UploadFTP(string LeSource, string Desti, string CodeClient)
{
Pers_Conf oConf = LeConf.Get_Config(CodeClient);
// Get the object used to communicate with the server.
FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://" + oConf.FtpServer + oConf.FtpChemin +"/" + Desti);
request.Method = WebRequestMethods.Ftp.UploadFile;
// This example assumes the FTP site uses anonymous logon.
request.Credentials = new NetworkCredential(oConf.FtpLogin, oConf.FtpPwd);
request.UseBinary = true;
request.UsePassive = true;
// Copy the contents of the file to the request stream.
StreamReader sourceStream = new StreamReader(LeSource);
byte [] fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
sourceStream.Close();
request.ContentLength = fileContents.Length;
Stream requestStream = request.GetRequestStream();
requestStream.Write(fileContents, 0, fileContents.Length);
requestStream.Close();
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
//Console.WriteLine("Upload File Complete, status {0}", response.StatusDescription);
response.Close();
}
}
this line is not work : Stream requestStream = request.GetRequestStream();
Anybody have solution ?
i have change the right into 777.
Thanks you in advance,
Stev
The Solutions
/ work only several ftp servers, but // it works perfectly everywhere

FtpWebRequest not downloading more then 8820 bytes of data

I am trying to transfer files between a couple of sites and I'm using FtpWebRequest to download the file from site A and upload it to site B.
The problem I'm facing is when I am downloading the file I'm not getting more then 8820 bytes of data.
Heres the code I am using:
public FtpFile Download(string path)
{
string fullpath = ConstructFullpath(path);
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(fullpath);
request.Method = WebRequestMethods.Ftp.DownloadFile;
// login
request.Credentials = new NetworkCredential(Username, Password);
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
Stream responseStream = request.GetResponse().GetResponseStream();
byte[] data = new byte[20000];
int length = responseStream.Read(data, 0, data.Length);
responseStream.Close();
FtpFile file = new FtpFile(path, data, length);
return file;
}
public bool Upload(FtpFile file)
{
if (!DirectoryExists(GetDirectory(file.Path)))
{
CreateDirectory(GetDirectory(file.Path));
}
string fullpath = ConstructFullpath(file.Path);
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(fullpath);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential(Username, Password);
Stream stream = request.GetRequestStream();
stream.Write(file.Data, 0, file.Length);
stream.Close();
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
return true;
}
The First image shows the source directory.
The second image shows the destination directory.
I have tried saving the files locally and have the same result.
You're only calling Read once:
byte[] data = new byte[20000];
int length = responseStream.Read(data, 0, data.Length);
responseStream.Close();
There's no guarantee that all the data will be read in a single call, and you should never rely on it doing so. You should loop round (e.g. copying the data into a MemoryStream) until Read returns 0.
If you're using .NET 4, Stream.CopyTo makes this easy:
MemoryStream ms = new MemoryStream();
responseStream.CopyTo(ms);
Note that you should also use using statements instead of closing resources explicitly, and that includes the FtpWebResponse.

FtpWebRequest Download File

The following code is intended to retrieve a file via FTP. However, I'm getting an error with it.
serverPath = "ftp://x.x.x.x/tmp/myfile.txt";
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(serverPath);
request.KeepAlive = true;
request.UsePassive = true;
request.UseBinary = true;
request.Method = WebRequestMethods.Ftp.DownloadFile;
request.Credentials = new NetworkCredential(username, password);
// Read the file from the server & write to destination
using (FtpWebResponse response = (FtpWebResponse)request.GetResponse()) // Error here
using (Stream responseStream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(responseStream))
using (StreamWriter destination = new StreamWriter(destinationFile))
{
destination.Write(reader.ReadToEnd());
destination.Flush();
}
The error is:
The remote server returned an error: (550) File unavailable (e.g., file not found, no access)
The file definitely does exist on the remote machine and I am able to perform this ftp manually (i.e. I have permissions). Can anyone tell me why I might be getting this error?
I know this is an old Post but I am adding here for future reference. Here is a solution that I found:
private void DownloadFileFTP()
{
string inputfilepath = #"C:\Temp\FileName.exe";
string ftphost = "xxx.xx.x.xxx";
string ftpfilepath = "/Updater/Dir1/FileName.exe";
string ftpfullpath = "ftp://" + ftphost + ftpfilepath;
using (WebClient request = new WebClient())
{
request.Credentials = new NetworkCredential("UserName", "P#55w0rd");
byte[] fileData = request.DownloadData(ftpfullpath);
using (FileStream file = File.Create(inputfilepath))
{
file.Write(fileData, 0, fileData.Length);
file.Close();
}
MessageBox.Show("Download Complete");
}
}
Updated based upon excellent suggestion by Ilya Kogan
Easiest way
The most trivial way to download a binary file from an FTP server using .NET framework is using WebClient.DownloadFile:
WebClient client = new WebClient();
client.Credentials = new NetworkCredential("username", "password");
client.DownloadFile(
"ftp://ftp.example.com/remote/path/file.zip", #"C:\local\path\file.zip");
Advanced options
Use FtpWebRequest, only if you need a greater control, that WebClient does not offer (like TLS/SSL encryption, progress monitoring, ascii/text transfer mode, resuming transfers, etc). Easy way is to just copy an FTP response stream to FileStream using Stream.CopyTo:
FtpWebRequest request =
(FtpWebRequest)WebRequest.Create("ftp://ftp.example.com/remote/path/file.zip");
request.Credentials = new NetworkCredential("username", "password");
request.Method = WebRequestMethods.Ftp.DownloadFile;
using (Stream ftpStream = request.GetResponse().GetResponseStream())
using (Stream fileStream = File.Create(#"C:\local\path\file.zip"))
{
ftpStream.CopyTo(fileStream);
}
Progress monitoring
If you need to monitor a download progress, you have to copy the contents by chunks yourself:
FtpWebRequest request =
(FtpWebRequest)WebRequest.Create("ftp://ftp.example.com/remote/path/file.zip");
request.Credentials = new NetworkCredential("username", "password");
request.Method = WebRequestMethods.Ftp.DownloadFile;
using (Stream ftpStream = request.GetResponse().GetResponseStream())
using (Stream fileStream = File.Create(#"C:\local\path\file.zip"))
{
byte[] buffer = new byte[10240];
int read;
while ((read = ftpStream.Read(buffer, 0, buffer.Length)) > 0)
{
fileStream.Write(buffer, 0, read);
Console.WriteLine("Downloaded {0} bytes", fileStream.Position);
}
}
For GUI progress (WinForms ProgressBar), see:
FtpWebRequest FTP download with ProgressBar
Downloading folder
If you want to download all files from a remote folder, see
C# Download all files and subdirectories through FTP.
This paragraph from the FptWebRequest class reference might be of interest to you:
The URI may be relative or absolute.
If the URI is of the form
"ftp://contoso.com/%2fpath" (%2f is
an escaped '/'), then the URI is
absolute, and the current directory is
/path. If, however, the URI is of the
form "ftp://contoso.com/path", first
the .NET Framework logs into the FTP
server (using the user name and
password set by the Credentials
property), then the current directory
is set to /path.
I had the same issue!
My solution was to insert the public_html folder into the download URL.
Real file location on the server:
myhost.com/public_html/myimages/image.png
Web URL:
www.myhost.com/myimages/image.png
private static DataTable ReadFTP_CSV()
{
String ftpserver = "ftp://servername/ImportData/xxxx.csv";
FtpWebRequest reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpserver));
reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
Stream responseStream = response.GetResponseStream();
// use the stream to read file from FTP
StreamReader sr = new StreamReader(responseStream);
DataTable dt_csvFile = new DataTable();
#region Code
//Add Code Here To Loop txt or CSV file
#endregion
return dt_csvFile;
}
I hope it can help you.
public void download(string remoteFile, string localFile)
{
private string host = "yourhost";
private string user = "username";
private string pass = "passwd";
private FtpWebRequest ftpRequest = null;
private FtpWebResponse ftpResponse = null;
private Stream ftpStream = null;
private int bufferSize = 2048;
try
{
ftpRequest = (FtpWebRequest)FtpWebRequest.Create(host + "/" + remoteFile);
ftpRequest.Credentials = new NetworkCredential(user, pass);
ftpRequest.UseBinary = true;
ftpRequest.UsePassive = true;
ftpRequest.KeepAlive = true;
ftpRequest.Method = WebRequestMethods.Ftp.DownloadFile;
ftpResponse = (FtpWebResponse)ftpRequest.GetResponse();
ftpStream = ftpResponse.GetResponseStream();
FileStream localFileStream = new FileStream(localFile, FileMode.Create);
byte[] byteBuffer = new byte[bufferSize];
int bytesRead = ftpStream.Read(byteBuffer, 0, bufferSize);
try
{
while (bytesRead > 0)
{
localFileStream.Write(byteBuffer, 0, bytesRead);
bytesRead = ftpStream.Read(byteBuffer, 0, bufferSize);
}
}
catch (Exception) { }
localFileStream.Close();
ftpStream.Close();
ftpResponse.Close();
ftpRequest = null;
}
catch (Exception) { }
return;
}
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(serverPath);
After this you may use the below line to avoid error..(access denied etc.)
request.Proxy = null;
FYI, Microsoft recommends not using FtpWebRequest for new development:
We don't recommend that you use the FtpWebRequest class for new development. For more information and alternatives to FtpWebRequest, see WebRequest shouldn't be used on GitHub.
The GitHub link directs to this SO page which contains a list of third-party FTP libraries, such as FluentFTP.

Categories