Download files using FluentFTP - c#

I am trying to implement FTP transfer using FluentFTP in C#. Getting a directory listing is very easy, but I am stuck on downloading files.
I found one article that has an example in its comments here but it won't compile because I cannot find where the class FtpFile comes from.
Does anybody have an example of how tocan I download a file from an ftp server using FluentFTP ?
EDIT: I found some examples here https://github.com/hgupta9/FluentFTP But there is no example on how to actually download a file.
In the this article Free FTP Library there is an example but it does not compile. This is the example
FtpClient ftp = new FtpClient(txtUsername.Text, txtPassword.Text, txtFTPAddress.Text);
FtpListItem[] items = ftp.GetListing();
FtpFile file = new FtpFile(ftp, "8051812.xml"); // THIS does not compile, class FtpFile is unknown
file.Download("c:\\8051812.xml");
file.Name = "8051814.xml";
file.Download("c:\\8051814.xml");
ftp.Disconnect();
EDIT: The solution
The article I found contained an example that set me in the wrong direction.
It seems there was once a Download method but that is gone long ago now.
So the answer was to let that go and use the OpenRead() method to get a stream and than save that stream to a file.

There are now DownloadFile() and UploadFile() methods built into the latest version of FluentFTP.
Example usage from https://github.com/robinrodricks/FluentFTP#example-usage:
// connect to the FTP server
FtpClient client = new FtpClient();
client.Host = "123.123.123.123";
client.Credentials = new NetworkCredential("david", "pass123");
client.Connect();
// upload a file
client.UploadFile(#"C:\MyVideo.mp4", "/htdocs/big.txt");
// rename the uploaded file
client.Rename("/htdocs/big.txt", "/htdocs/big2.txt");
// download the file again
client.DownloadFile(#"C:\MyVideo_2.mp4", "/htdocs/big2.txt");

Related

.NET FTP Upload file and preserve original date time

We have a Windows 2008 R2 web server with FTP over SSL. This app uses .NET 4.5 and when I upload files, the date/time on the file changes to the current date/time on the server. Is there a way to have the uploaded file preserve the original (last modified) date?
Here is what I have:
FtpWebRequest clsRequest = (FtpWebRequest)WebRequest.Create(FTPFilePath);
clsRequest.EnableSsl = true;
clsRequest.UsePassive = true;
clsRequest.Credentials = new NetworkCredential(swwwFTPUser, swwwFTPPassword);
clsRequest.Method = WebRequestMethods.Ftp.UploadFile;
Byte[] bFile = File.ReadAllBytes(LocalFilePath);
Stream clsStream = clsRequest.GetRequestStream();
clsStream.Write(bFile, 0, bFile.Length);
clsStream.Close();
clsStream.Dispose();
clsRequest = null;
There's really no standard way to update timestamp of a remote file over an FTP protocol. That's probably why the FtpWebRequest does not support it.
There are two non-standard ways to update the timestamp. Either a non-standard MFMT command:
MFMT yyyymmddhhmmss path
or a non-standard use of (otherwise standard) MDTM command:
MDTM yyyymmddhhmmss path
But the FtpWebRequest does not allow you to send a custom command either.
See for example How to send arbitrary FTP commands in C#.
So you have to use a 3rd party FTP library.
For example WinSCP .NET assembly preserves a timestamp of an uploaded file by default.
// Setup session options
SessionOptions sessionOptions = new SessionOptions
{
Protocol = Protocol.Ftp,
HostName = "example.com",
UserName = "user",
Password = "mypassword",
};
using (Session session = new Session())
{
// Connect
session.Open(sessionOptions);
// Upload
session.PutFiles(#"c:\toupload\file.txt*", "/home/user/").Check();
}
See a full example.
Note that WinSCP .NET assembly is not a native .NET assembly. It's rather a thin .NET wrapper around a console application.
(I'm the author of WinSCP)
I know that we can assign file attributes:-
//Change the file created time.
File.SetCreationTime(path, dtCreation);
//Change the file modified time.
File.SetLastWriteTime(path, dtModified);
If you can extract the original date before you save it to the server, then you can change file attributes....something like this:-
Sftp sftp = new Sftp();
sftp.Connect(...);
sftp.Login(...);
// upload the file
sftp.PutFile(localFile, remoteFile);
// assign creation and modification time attributes
SftpAttributes attributes = new SftpAttributes();
System.IO.FileInfo info = new System.IO.FileInfo(localFile);
attributes.Created = info.CreationTime;
attributes.Modified = info.LastWriteTime;
// set attributes of the uploaded file
sftp.SetAttributes(remoteFile, attributes);
I hope this points you in the right direction.
This is an older question, but I will add my solution here. I used an approach similar to the solution proposed by #Martin Prikryl, using the MDTM command. His answer shows the DateTime format string as yyyymmddhhmmss which is incorrect since it does not correctly handle the month and 24 hour time format. In this answer I corrected this issue and provided a full solution using C#.
I used the FluentFTP library which handles many other aspects of working with an FTP through C# very well. To set the modified time, this library does not support it but it has an Execute method. Using the FTP command MDTM yyyyMMddHHmmss /path/to/file.txt will set the modified time of the file.
NOTE: in my instance I needed to use the universal time, which may be the case for you.
The code below shows how to connect to the FTP and set the last modified time using the Execute method and sending the MDTM command.
FtpClient client = new FtpClient("ftp-address", "username", "password");
client.Connect();
FtpReply reply = client.Execute($"MDTM {DateTime.UtcNow.ToString("yyyyMMddHHmmss")} /path/to/file.txt");

Get last modified date of a remote file

I have an app with which at startup it downloads a file from a remote location (through the net) and parses it's contents.
I am trying to speed up the process of startup as the bigger the file gets the slower the app starts.
As a way to speed up the process I thought of getting the last modified date of the file and if it is newer from the file on the user's pc then and only then download it.
I have found many ways to do it online but none of them are in C# (for windows store apps). Does anybody here know of a way of doing this without the need to download the file? If I am to download the file then the process is sped up at all.
My C# code for downloading the file currently is this
const string fileLocation = "link to dropbox";
var uri = new Uri(fileLocation);
var downloader = new BackgroundDownloader();
StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync("feedlist.txt",CreationCollisionOption.ReplaceExisting);
DownloadOperation download = downloader.CreateDownload(uri, file);
await download.StartAsync();
If it helps the file is stored in dropbox but if any of you guys have a suggestion for another free file hosting service I am open to suggestions
Generally, you can check the file time by sending HEAD request and parsing/looking HTTP header response for a Last-Modified filed. The remote server should support it and DropBox does not support this feature for direct links (only via API). But DropBox have another feature, the headers have the etag field. You should store it and check in the next request. If it changed - the file has been changed too. You can use this tool to check the remote file headers.

c# FTP to FileZilla Server file name save issue

Whenever I use this code it uploads the jpeg, but the jpegs name is STOR with no extension on the server.
Any idea as to why this happens or how I change the file name when saving from my C# desktop application to my FileZilla FTP Server??
Here is the basic code, the names have been changes to protect the innocent ;)
WebClient client = new WebClient();
client.Credentials = new NetworkCredential("username", "password");
client.BaseAddress = "ftp://mysite.com";
client.UploadFile(WebRequestMethods.Ftp.UploadFile, "C:\mypics\pic1.jpg");
Try
client.UploadFile(remoteName, WebRequestMethods.Ftp.UploadFile , #"C:\mypics\pic1.jpg");
WebRequestMethods.Ftp.UploadFile is a string whose value happens to be STOR so the compiler is assuming your are using the client.UploadFile(remoteName, localName) overload which is why your file is named STOR
#sgmoore answered the question. You need just use method correctly:
client.UploadFile("pic1.jpg", "C:\mypics\pic1.jpg");
first argument is remote file name, second is path to local file.
You can also try some other ftp client implementations in .net (anyway FTP is implemented badly in .NET standard library), I've used ftplib and it's working good.

Upload and rename multiple files to FTP using asp.net

We are creating CMS, in which we want to have the option to upload multiple files to FTP server. The steps are
Open FTP connection
Click browse - Select multiple files - Click upload to FTP
Create a folder on the FTP server
Rename the selected files and upload them to the folder
Close the connection
It will be good if it shows the status of the upload.
We are using asp.net with C#. Any sample code will help. Is there any good components available. I can spend max of $150 to buy a component.
Please help. Thanks in advance.
First of all, you should use an open source CMS and improve the code to your needs, don't try to reinvent the wheel!
Second, there is no need to spend money, plenty of solutions out there ...
you can use, for example Uploadify to pass user files to your server, then using any FTP Example upload the files to the FTP and delete them from the server upon success.
if you don't want to have the "middle men", just upload directly to the FTP
string name = Path.GetFileName(UploadControl.FileName);
byte[] data = UploadControl.FileBytes;
using (WebClient client = new WebClient()) {
client.UploadData("ftp://my.ftp.server.com/myfolder/" + name, data);
}

Create folder on ftp

I am using method to create folder on ftp i want get exception if folder already exsists how to make it over write the existing folder
using System; using System.Net;
class Test {
static void Main()
{
WebRequest request = WebRequest.Create("ftp://host.com/directory");
request.Method = WebRequestMethods.Ftp.MakeDirectory;
request.Credentials = new NetworkCredential("user", "pass");
using (var resp = (FtpWebResponse) request.GetResponse())
{
Console.WriteLine(resp.StatusCode);
}
} }
it is "remote server returned error (550) file not found"
Well, "I want to get exception if folder already exists" and "how to make it overwrite the existing folder" are two opposing questions.
At any rate, I just implemented code to do this the other day. Just check if the directory already exists first. And then respond based on that. There's no point in trying to create a directory that already exists.
And if you need to overwrite it somehow, then delete the existing directory before creating the new one.
You can see the code I wrote for this in the article An FtpClient Class and WinForm Control, although it will just overwrite existing content.
You might want to consider some existing ftp libs out there. I've been using this and have had great success with it. It's an FTP client library that provides high-level FTP functionality for the FTPrequest in the .NET Framework 2.0.
It has an API for checking if directory exists and for creating the directory.
Code # http://ftpclient.codeplex.com/
Article # http://www.codeproject.com/KB/IP/FtpClient.aspx
I use this func in solution
private void createFolder(string ftpUName, string ftpPWord)
{
WebRequest ftpRequest = WebRequest.Create("ftp://mrhotro.ad/new_sc");
ftpRequest.Method = WebRequestMethods.Ftp.MakeDirectory;
ftpRequest.Credentials = new NetworkCredential(ftpUName, ftpPWord);
}
You can't overwrite an existing folder... I'm not even sure what benefit that might be.
In short, you need to capture the exception and decide what to do. Either leave it in place (after all, it already exists...) or you'll need to delete the existing folder and try to recreate it.
I don't remember if you can delete a folder that currently contains files.. If you can't, then you will have to delete those as well.

Categories