Solved

Download file from FTP in C# and save on Local drive

Posted on 2010-11-29
26
3,523 Views
Last Modified: 2012-05-10
Hi,

I need sample code example how to download a file from ftp server in C# and put it in a local drive.
0
Comment
Question by:nkc1112
  • 13
  • 10
  • +2
26 Comments
 
LVL 52

Expert Comment

by:Carl Tawn
ID: 34232639
0
 
LVL 13

Expert Comment

by:iHadi
ID: 34235291
Hi

Try the following code
/// <summary>
/// Download file using Ftp
/// </summary>
/// <param name="ftpFile">The ftp file path, example: ftp://123.456.789.123/files/test.txt</param>
/// <param name="localFile">The file path where to store the file downloaded, example: C:\test.txt</param>
private void Download(string ftpFile, string localFile)
{
    FtpWebRequest reqFTP;
    string ftpServerIP = "";
    string ftpUserID = "";
    string ftpPassword = "";

    try
    {
        //filePath = <<The full path where the 

        //file is to be created. the>>, 

        //fileName = <<Name of the file to be createdNeed not 

        //name on FTP server. name name()>>

        FileStream outputStream = new FileStream(localFile);

        reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpFile));

        reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
        reqFTP.UseBinary = true;
        reqFTP.Credentials = new NetworkCredential(ftpUserID,
                                                    ftpPassword);
        FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
        Stream ftpStream = response.GetResponseStream();
        long cl = response.ContentLength;
        int bufferSize = 2048;
        int readCount;
        byte[] buffer = null;

        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();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

Open in new window

0
 
LVL 21

Expert Comment

by:Alpesh Patel
ID: 34236691
Hi,

To get file form FTP server

Create FTP Request using actual ftp path.
Wait for response in Stream.
Save file to local path.
0
 

Author Comment

by:nkc1112
ID: 34239382
Thanks guys, I will try with you suggestions but My problem is,

On FTP Server files are placed on daily basis, I need to read the file that is latest one. File name on ftp server will have in following format:
   filenameMM-DD-YYYY.csv

Can any one help me in this regard?
0
 
LVL 13

Expert Comment

by:iHadi
ID: 34239696
Hi

You can use the following code to list all the files in the ftp directory. The bad part is that there isn't any standard way on how the results are returned. Each ftp server returns the result in its own format. You need to use regex to parse the results and get the file names.

After you get all the files and find the name of the file you are looking for, you can then download it.
// Get the object used to communicate with the server.
            FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://www.yourFtpPath.com/");
            request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;

            // This example assumes the FTP site uses anonymous logon.
            request.Credentials = new NetworkCredential ("username","password");

            FtpWebResponse response = (FtpWebResponse)request.GetResponse();
    
            Stream responseStream = response.GetResponseStream();
            StreamReader reader = new StreamReader(responseStream);
            Console.WriteLine(reader.ReadToEnd());

            Console.WriteLine("Directory List Complete, status {0}", response.StatusDescription);
    
            reader.Close();
            response.Close();

Open in new window

0
 

Author Comment

by:nkc1112
ID: 34239771
I am trying to download a file from a FTP server that has the current date only. There are multiple files on the server. Each day a new file is added. So i need to download only that file (current date) and move that to a local folder. In the code above, i can name a specific file and successfully download it. Hope I make sense.

Format of file to downolad is .CSV
0
 
LVL 13

Expert Comment

by:iHadi
ID: 34239955
Ok, the above code I just posted lists the files in your ftp directory, that means it gets all the names of the files. for example:

file03-04-2010.csv
file03-05-2010.csv
file03-06-2010.csv

What you have to do is get the date of each file from its name and compare them to find out the most recent file.

Once you find it, use its name to download it from the server.

The problem is that I don't know the format that your ftp server returns the files list. If you can post the files list the way you receive it in the ftp response (prefer it in an attached txt file), I can help you with the code that determines the file you should download
0
 

Author Comment

by:nkc1112
ID: 34240148
Hi,

Can we direclty get one file direclty from ftp? my process runs every day to get the latest file. File name on ftp server in following format like xyzmm-dd-yyyy.csv.  Can you help me how to send filename in that particular format in my request line?  following is the code i am doing:

string  dateString = DateTime.Now.ToString("MM-dd-yyyy");
                filename = string.Format("xys.csv", dateString);                
                FtpWebRequest request = (FtpWebRequest)WebRequest.Create(new Uri("ftp://" + ftpServerIp + "/" + filename));

still i get filename as xyz.csv not as xyzmm-dd-yyyy.csv.

Can any one help me how to add today's date to filename.  For e.g.  xyz.csv is my file name but i need to change it to xyz11-30-2010.csv.  

After that once the file is read from ftp how can i save it in my local folder?
0
 
LVL 13

Expert Comment

by:iHadi
ID: 34240287
Use the following line instead of yours

filename = string.Format("xys{0}.csv", dateString);

After that download it to the path you want using the Download method after specifying the local path for it using the localfile parameter:

string localpath = "yourLocalDirectory" + filename.csv

 
0
 

Author Comment

by:nkc1112
ID: 34240345
Hey thanks it worked for me, but i have last question:

i am getting the file from ftp server and i am reading using following code but after reading how can i save to local folder?

 FtpWebResponse response = (FtpWebResponse)request.GetResponse();
                Stream ftpStream = response.GetResponseStream();
                StreamReader reader = new StreamReader(ftpStream);
                reader.ReadToEnd();

reading the file to the end, then i need how can i write to antoher file and save it on local folder?
0
 
LVL 13

Expert Comment

by:iHadi
ID: 34240439
This is written in the Download() method above:

FileStream outputStream = new FileStream(localFile);

Where the localFile is the path and filename you want to save your file, for example "c:\\my.csv".

The following code saves the bytes from the response to the local file:

        long cl = response.ContentLength;
        int bufferSize = 2048;
        int readCount;
        byte[] buffer = null;

        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();
0
 

Author Comment

by:nkc1112
ID: 34240478
I have tried above one, getting following error at
readcount= fltpstream.read(buffer,0,readcount);

[System.ArgumentNullException] = {"Value cannot be null.\r\nParameter name: buffer"}

one more question is when i debug i get value of cl=-1, so i am confused when i am getting it as -1?
0
 
LVL 13

Expert Comment

by:iHadi
ID: 34240791
replace the:  byte[] buffer = null;
with: byte[] buffer = new byte[bufferSize];
0
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 

Author Comment

by:nkc1112
ID: 34240914
Thanks for reply, but i have used another way to download the file,

           FileStream outputstream = new FileStream(filepath + "\\" + filename, FileMode.Create);

                WebClient req = new WebClient();
                req.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
                byte[] filedata = req.DownloadData("ftp://" + ftpServerIp + "/" + filename);
                outputstream.Write(filedata, 0, filedata.Length);
                outputstream.Close();

Now i got one more problem is that, i need to get entire files on ftp and just need to read the files that are not in my local. I hope you understand:

To be more clear, I want to get all the files from ftp server every day, but my code should just read the data from the file that is not present in my local folder.
0
 
LVL 13

Expert Comment

by:iHadi
ID: 34240981
first of all, the method you are using for the download works for small to mid size files
big files can cause you problems with this method

for your other issue, you need to list the files as I mentioned earlier

after you do that, you should look for the files in you local directory and exclude the ones that exist in the local from downloading
0
 

Author Comment

by:nkc1112
ID: 34241070
I am getting the file with your sample code provided, can you please provide me with some sample code how exaclty i can compare file names from ftp with my local folder file names and then how to download that particular file not present in my local folder?

0
 

Author Comment

by:nkc1112
ID: 34241411
  FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://" + ftpServerIp + "/");
                request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
                request.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
                StreamReader sr = new StreamReader(request.GetResponse().GetResponseStream());
                string str = sr.ReadLine();
                while (str != null)
                {
                    strList.Add(str);
                    str = sr.ReadLine();
                }

Now getting files from ftp server in one List<string> strlist, similary i can get all the files from my folder into one more list array now i need to find the file from sttlist name that is not in my local folder and to download it...

i know the donwload process once i get the file name, but please help me with logic how to get the file name?
0
 
LVL 13

Expert Comment

by:iHadi
ID: 34241580
Can you post the string str value after it receives it from the ftp server
0
 
LVL 13

Accepted Solution

by:
iHadi earned 500 total points
ID: 34241725
Try the following:
private string[] GetFilesToDownload(string ftpList)
{
    string localDir = "d:\\mydir";
    List<string> nonExistsFileNames = new List<string>();
    List<string> fileNames = new List<string>();
    MatchCollection matches = Regex.Matches(ftpList, @"[\w-]+\.csv");

    foreach (Match m in matches)
    {
        fileNames.Add(m.Value);
    }


    foreach (string str in fileNames)
    {
        string filepath = Path.Combine(localDir, str);
        bool exists = File.Exists(filepath);
        if (!exists)
            nonExistsFileNames.Add(str);
    }

    return nonExistsFileNames.ToArray();

}

Open in new window

0
 
LVL 13

Expert Comment

by:iHadi
ID: 34241745
the ftp list is:  string str = sr.ReadToEnd();
from your code of getting the list of files
0
 

Author Comment

by:nkc1112
ID: 34241814
I am getting my strlist following data:

11-09-10  10:55AM              2460982  XYZcompletions.csv
11-11-10  01:30AM                 1475  XYZdailycompletions11-11-2010.csv

Now my local directory list string contains:
C:\Sample\Local\AImp\XYZdailycompletions11-12-2010.csv

I got both list of string arrays with the data.. need to compare them, just need to compare only name of files..

Please help me out
0
 

Author Comment

by:nkc1112
ID: 34241902
11-09-10  10:55AM              2460982 XYZcompletions.csv
11-09-10  11:23AM               116618 XYZcourses.csv
11-09-10  11:33AM                 1793 XYZdailycompletions11-09-2010.csv
11-10-10  01:30AM                  606 XYZdailycompletions11-10-2010.csv
11-11-10  01:30AM                 1475 XYZdailycompletions11-11-2010.csv

this my str when i use string str= sr.ReadToEnd();

ANy idea how to get just file name only?
0
 

Author Comment

by:nkc1112
ID: 34241917
Ya i got it how to just get the file names. so my Str is ready now.

I will try comparuing with you above posted code!
0
 

Author Comment

by:nkc1112
ID: 34243414
public void ReadFileFromFTP()
        {
            List<string> strList = new List<string>();
            try
            {
                ftpServerIp = Convert.ToString(ConfigurationManager.AppSettings["FtpServerIp"]);
                ftpUserID = Convert.ToString(ConfigurationManager.AppSettings["FtpUserID"]);
                ftpPassword = Convert.ToString(ConfigurationManager.AppSettings["FtpPassword"]);
                filepath =ImportPath;

                FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://" + ftpServerIp + "/");
                request.Method = WebRequestMethods.Ftp.ListDirectory;
                request.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
                StreamReader sr = new StreamReader(request.GetResponse().GetResponseStream());
                //string str = sr.ReadToEnd();
                string[] array=GetFilesToDownload(sr.ReadToEnd());
                foreach (string file in array)
                {
                    FileStream outputstream = new FileStream(filepath + "\\" + file, FileMode.Create);
                    FtpWebRequest ftpreq = (FtpWebRequest)WebRequest.Create("ftp://" + ftpServerIp + "/" + file);
                    ftpreq.Method = WebRequestMethods.Ftp.DownloadFile;
                    ftpreq.UseBinary = true;
                    FtpWebResponse response = (FtpWebResponse)request.GetResponse();
                    Stream ftpStream = response.GetResponseStream();
                    long c1 = 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);
                    }

                 
                }                                          
       
            }
            catch (Exception ex)
            {
               
            }
           

        }
        private string[] GetFilesToDownload(string ftpList)
        {
            string localDir = AfterImportPath;
            List<string> nonExistsFileNames = new List<string>();
            List<string> fileNames = new List<string>();
            MatchCollection matches = Regex.Matches(ftpList, @"[\w-]+\.csv");

            foreach (Match m in matches)
            {
                fileNames.Add(m.Value);
            }


            foreach (string str in fileNames)
            {
                string filepath = Path.Combine(localDir, str);
                bool exists = File.Exists(filepath);
                if (!exists)
                    nonExistsFileNames.Add(str);
            }

            return nonExistsFileNames.ToArray();          
        }

I get following error, cannot access the disposed object @ readcount = ftpStream.Read(buffer, 0, bufferSize);
 i.e. before while(readcount>0)?? can any one help me what is wrong in my code?
0
 

Author Comment

by:nkc1112
ID: 34243456
Following is the error:

Cannot access a disposed object.
Object name: 'System.Net.Sockets.NetworkStream'.
0
 
LVL 12

Expert Comment

by:jagssidurala
ID: 34245256
0

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now