FTP download not writing the data in the file - c#

I have written a program that downloads a file from a remote ftp site and saves it to the local c drive then uploads that file to a separate server. The problem now is that when the file gets downloaded, there is no data inside the text file it creates on the local C and I can't figure out why that is. Here is the code I'm using
// Download File
public void download(string remoteFile, string localFile)
{
try
{
// Create an FTP Request
ftpRequest = (FtpWebRequest)FtpWebRequest.Create(downhost + "/" + remoteFile);
// Log in to the FTP Server with the User Name and Password Provided
ftpRequest.Credentials = new NetworkCredential(downuser, downpass);
// When in doubt, use these options
ftpRequest.UseBinary = true;
ftpRequest.UsePassive = true;
ftpRequest.KeepAlive = true;
/* Set HTTP Proxy to Null to avoid The Requested FTP Command Is Not Supported When Using HTTP Proxy error */
ftpRequest.Proxy = null;
// Specify the Type of FTP Request
ftpRequest.Method = WebRequestMethods.Ftp.DownloadFile;
// Establish Return Communication with the FTP Server
ftpResponse = (FtpWebResponse)ftpRequest.GetResponse();
// Get the FTP Server's Response Stream
ftpStream = ftpResponse.GetResponseStream();
// Open a File Stream to Write the Downloaded File
FileStream localFileStream = new FileStream(localFile, FileMode.Create);
// Buffer for the Downloaded Data
byte[] byteBuffer = new byte[bufferSize];
int bytesRead = ftpStream.Read(byteBuffer, 0, bufferSize);
// Download the File by Writing the Buffered Data Until the Transfer is Complete
try
{
while (bytesRead > 0)
{
localFileStream.Write(byteBuffer, 0, bytesRead);
bytesRead = ftpStream.Read(byteBuffer, 0, bufferSize);
}
}
catch (Exception ex) { Console.WriteLine(ex.ToString()); }
// Resource Cleanup
localFileStream.Close();
ftpStream.Close();
ftpResponse.Close();
ftpRequest = null;
}
catch (Exception ex) { Console.WriteLine(ex.ToString()); }
return;
}
I used the code found at http://www.codeproject.com/Tips/443588/Simple-Csharp-FTP-Class as the basis to build my program off of and I've done Google searches on how other people have written their ftp download scripts but can't figure out any reason why the data isn't being written.
Any help is appreciated.

Flush the file. Call localFileStream.Flush(); before you close it.

I realise that this is a bit late, but i was having the same issue trying to use that example, i managed to get a FTP download working with an example from here:
http://www.techrepublic.com/blog/howdoi/how-do-i-use-c-to-upload-and-download-files-from-an-ftp-server/165

I'm having issues with the same method. I did find a way to get the system to work but I had to copy the ftpstream in your code to another stream like this: (in vb.net, I know, I'm sorry)
ftpStream.copyTo(MySecondStream)
ftpStream.close()
'do whatever you want with the copy now
Return MySecondStream
Maybe it has something to do with how the initial stream is handled and how long it stays open. I posted my question here: Why do I have to copy an FTP stream to another variable to return it to the calling method?

I had the same problem on an upload. 0 bytes written. Code was working on one FTP server, but not on another. Just had to do the following:
client.FtpStream.Flush();
client.FtpStream.Close();

Related

Use SFTP instead of FTP in older version of C# (2010 Express)

I have to change an older C# script (created back in 2010 in C# Express) to use SFTP instead of FTP. It took some doing to get this script out of an old repository - and to download a version of C# 2010 Express to get the script open! But I finally managed it. I have never coded in C# so please be kind. We have several off-site PCs that need to transfer files to and from the server on their network. This script is a .dll which is referenced in several other programs on these systems, so I'll need to change the calls to this .dll in those scripts as well. I have researched using SFTP in C# and from what I've seen thought it was best to install Renci.SshNet, so that has been installed as a reference in the project. What I'm looking to do is change the function below to use SFTP instead of FTP, but I'm not really sure how to even begin -
public TimeSpan FTPTo(string strFTPServer, string strLocalFileandPath, string strFTPFileandPath, string strFTPUser, string strFTPPassword)
{
try
{
DateTime dtStart = DateTime.Now;
FtpWebRequest ftp = (FtpWebRequest)FtpWebRequest.Create(strFTPServer + "/" + strFTPFileandPath);
ftp.Proxy = null;
ftp.Credentials = new NetworkCredential(strFTPUser, strFTPPassword);
//userid and password for the ftp server to given
ftp.KeepAlive = true;
ftp.UseBinary = true;
ftp.Method = WebRequestMethods.Ftp.UploadFile;
FileStream fs = File.OpenRead(strLocalFileandPath);
byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);
fs.Close();
Stream ftpstream = ftp.GetRequestStream();
ftpstream.Write(buffer, 0, buffer.Length);
ftpstream.Close();
return DateTime.Now - dtStart;
}
catch (Exception ex1)
{
throw ex1;
}
}
Any suggestions/help would be greatly appreciated.
To upload a file to an SFTP server using SSH.NET, use SftpClient.UploadFile.
A trivial example is like:
var client = new SftpClient("example.com", "username", "password");
client.Connect();
using (var sourceStream = File.Open(#"C:\local\path\file.ext"))
{
client.UploadFile(sourceStream, "/remote/path/file.ext");
}
There's no relation to your original code. The API is completely different. You basically have to start from the scratch.

C# FTP connect to specific PATH bypassing the ROOT

I need to upload files to a specific folders in my ftp server.
The problem is that the permission to access the ftp is limited to a specific folder which is not the root folder.
Sending this request gets me the error 550
.
It looks like my ftp request goes to the root and than changes to the directory. I need to send the request to the specific path. For example, if use mozilla i can easly do it and not receiving error.
(i receive 550 if i connect to the root path first only)
any ideas?
Uri target = new Uri("ftp://mtftpserver/folder");
try
{
ftpRequest = (FtpWebRequest)FtpWebRequest.Create(target);
ftpRequest.UseBinary = true;
ftpRequest.UsePassive = true;
ftpRequest.KeepAlive = true;
ftpRequest.Method = WebRequestMethods.Ftp.UploadFile;
ftpStream = ftpRequest.GetRequestStream();
FileStream localFileStream = new FileStream(localFile, FileMode.Create);
byte[] byteBuffer = new byte[bufferSize];
int bytesSent = localFileStream.Read(byteBuffer, 0, bufferSize);
try
{
while (bytesSent != 0)
{
ftpStream.Write(byteBuffer, 0, bytesSent);
bytesSent = localFileStream.Read(byteBuffer, 0, bufferSize);
}
}
catch (Exception ex) { Console.WriteLine(ex.ToString()); }
localFileStream.Close();
ftpStream.Close();
ftpRequest = null;
}
catch (Exception ex) { Console.WriteLine(ex.ToString()); }
return;
FTP error codes
Error 550 is "File unavailable due to access level"
If you connect to the FTP server without any credentials or account, you are automatically logging in as anonymous or guest user.
A guest user have a predefined root separate from the root folder of logged in users. Normally, the guest, anonymous user have a limited folder to work on.
You are trying to move to the another folder where the default user have no access, this is the one throwing the invalid access error or error 550.

Folder & Files Upload through ftp C#

i'm trying to learn something new about uploading through ftp connection to another host.
i know how to upload single file. but what if i want to upload full folder with its full subfolders and files that exists on it?
this is my one single file upload
private void Form1_Load(object sender, EventArgs e)
{
Upload("Test.txt");
}
public void Upload(string fileToUpload)
{
try
{
FileInfo toUpload = new FileInfo(fileToUpload);
FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://127.0.0.1/" + toUpload.Name);
MessageBox.Show(WebRequestMethods.Ftp.ListDirectory);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential("Uploader", "3635451");
Stream ftpStream = request.GetRequestStream();
FileStream file = File.OpenRead(fileToUpload);
int length = 1024;
byte[] buffer = new byte[length];
int bytesRead = 0;
do
{
bytesRead = file.Read(buffer, 0, length);
ftpStream.Write(buffer, 0, bytesRead);
}
while (bytesRead != 0);
file.Close();
ftpStream.Close();
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
i google'd alot about uploading folder but i have just failed
thank you in advance.
You could use the WinSCP library. It is free, and supports FTP as well as SFTP. I have found it easy to use, and works flawlessly.
The PutFiles method will process an entire folder, including sub-folders. It also has a SynchronizeDirectories method.
The answer is you cannot.
You may be interested by libraries for doing such operations, if not you can look at their source code.
If you want to upload a folder you have to create the folder on your FTP and then copy each file one by one.
Example of a folder on local:
/Folder/File1.txt
/Folder/File2.txt
If you want to upload the folder "Folder".
Create directory in FTP
Open the FTP directory
Copy "File1.txt"
Copy "File2.txt"

Ftp Upload gives exception Unable to write data to the transport connection. An existing connection was forcibly closed by the remote host

I have a windows form application in which i am using a background worker to ftp upload files. After uploading 209 files successfully it gave error on file which only had size of 7.8kb that While Processing Img1.jpg Unable to write data to the transport connection. An existing connection was forcibly closed by the remote host.
string uri1;
ftpInfoUpload = LoadHostedSiteData(hs);
ftpInfoUpload[5] = imgRow["Filename"].ToString();
uri1 = String.Format("ftp://{0}/{1}/images/{2}", ftpInfoUpload[1], ftpInfoUpload[2], ftpInfoUpload[5]);
requestUpload = (FtpWebRequest)WebRequest.Create(uri1);
requestUpload.UsePassive = false;
requestUpload.UseBinary = true;
requestUpload.Method = WebRequestMethods.Ftp.UploadFile;
requestUpload.Credentials = new NetworkCredential(ftpInfoUpload[3], ftpInfoUpload[4]);
requestUpload.ContentLength = memStream.Length;
byte[] buff = new byte[bufferSize];
int contentLen;
// Stream to which the file to be upload is written
Stream strm = requestUpload.GetRequestStream();
memStream.Seek(0, SeekOrigin.Begin);
contentLen = memStream.Read(buff, 0, bufferSize);
// 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, bufferSize);
}
//Close the file stream and the Request Stream
strm.Close();
strm.Dispose();
ftpStream.Close();
memStream.Close();
//responseUpload.Close();
responseDownload.Close();
And ideas whats happening?
I have set ftprequest.KeepAlive=true & set ftprequest.ConnectionGroupName = "Some Value", so that underlying code does not have to new create connection which have the same ftp server. I found this solution here. I also found this helpful. Also make sure not to create a new NetworkCredential object everytime you transfer a file that can cause exception. I have tested my code twice transferring 300 files and seems to work perfectly and quick. Setting KeepAlive=false can make transfers slow

Uploading file with c# ftp methods results in webexception. Problem disappears after program restart

I have following problem:
I'm using C# ftp methods to automate sending files to FTP servers. The program is constantly running, checking predefined directories. If it finds files in a directory, it is supposed to upload them to a defined ftp server. There are about 80 directories and most of the time the program has something to do. Everything works fine, except from the following scenario:
The file is being uploaded.
An error occurs while uploading: the remote host is down, the quota is exceeded or something similar.
An attempt is made to upload the file once again and the error occurs once again.
An attempt is made to upload file for the third, fourth, ... time and then this line of code:
Stream requestStream = ftpRequest.GetRequestStream();
throws WebException with status: Undefined, and description: the time limit for this operation has been reached (or something similar - I had to translate this from polish). While this WebException is being thrown, ftp request to other servers (files from different directories) succeed, so it looks like there is only problem with connection to this one ftp server.
It all results in no further attempt to upload file being successful. Uploading this file through other ftp client is, however, possible. When I restart the program, everything runs smoothly. Should I somehow manually release ftp resource? I'm using KeepAlive property of FtpWebRequest set to true..
I would very appreciate if someone could shed some light on this problem.
Edited:
I followed David's hint and found the place where I didn't call Close() method on the requestStream, I fixed it, but the problem reoccurred.
I will paste some code then. Here is part of the method, that uploads the file to the server. If it fails, another attempt is being made, something like:
while (retryCounter++ < retryNumber)
{
//upload file,
//if succeeded, break
}
inside while-block there is:
FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create(remoteFileName);
ftpRequest.UseBinary = true;
ftpRequest.UsePassive = true;
ftpRequest.Credentials = new NetworkCredential(UserName, Password);
ftpRequest.ReadWriteTimeout = SendTimeout;
ftpRequest.Timeout = ConnectTimeout;
ftpRequest.KeepAlive = true;
ftpRequest.Proxy = null;
ftpRequest.Method = WebRequestMethods.Ftp.UploadFile;
Stream requestStream = null;
try
{
using (MemoryStream fileStream = new MemoryStream(localFile))
{
byte[] buffer = new byte[BufferSize];
int readCount = fileStream.Read(buffer, 0, BufferSize);
int bytesSentCounter = 0;
while (readCount > 0)
{
requestStream.Write(buffer, 0, readCount);
bytesSentCounter += readCount;
readCount = fileStream.Read(buffer, 0, BufferSize);
System.Threading.Thread.Sleep(100);
}
}
requestStream.Close();
requestStream = null;
FtpWebResponse response = (FtpWebResponse)ftpRequest.GetResponse();
FtpStatusCode code = response.StatusCode;
string description = response.StatusDescription;
response.Close();
_logger.Information("Upload file result : status code {0}, status description {1}", code, description);
if (code == FtpStatusCode.ClosingData)
{
_logger.Information("File {0} uploaded successfully", localFileName);
}
else
{
_logger.Error("Uploading file {0} did not succeed. Status code is {1}, description {2}", localFileName, code, description);
}
}
catch (WebException ex)
{
if (requestStream != null)
requestStream.Close();
ftpRequest.Abort();
FtpStatusCode code = ((FtpWebResponse)ex.Response).StatusCode;
string description = ((FtpWebResponse)ex.Response).StatusDescription;
_logger.Error("A connection to the ftp server could not be established. Status code: {0}, description: {1} Exception: {2}. Retrying...", code, description, ex.ToString());
}
So, again the scenario is following:
1. The file is being uploaded and System.Net.Sockets.SocketException occurrs.
2. Another attempt is being made and System.Net.Sockets.SocketException reoccurs.
3. Always before I call the uploadfile method, I check whether the remote server is up and everything is ok by trying to list the remote directory. And from now, by calling
ftpRequest.GetResponse() (where ftpRequest.Method is WebRequestMethods.Ftp.ListDirectory) I get WebException with status: Undefined, and description: the time limit for this operation has been reached. When I restart the application, the problem disappears.
I can find no other place where the streams are not released properly, and have no idea what to do next..
Are you sure you're closing the stream correctly and thus release all underlying resources properly?
If not, this might be the cause of your problem, when you hit a limit (e.g. open sockets) after repeated failures.
You need to ensure you put the Stream.Close(), Request.Close() and Response.Close() in a finally block otherwise they will be skipped whenever there is an error. Keep in mind when dealing with external resources such as over a network, you need to program to expect errors since they will certainly crop up at some point.
try
{
processing here...
}
finally
{
requestStream.Close();
requestStream = null;
}
One possible source of error that I've run into is creating a new "NetworkCredential" over and over again. Then you'll get an exception after awhile.

Categories