• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 7473
  • Last Modified:

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

Hi,

I need sample code example how to download a file from ftp server in C# and put it in a local drive.
0
nkc1112
Asked:
nkc1112
  • 13
  • 10
  • +2
1 Solution
 
Carl TawnSystems and Integration DeveloperCommented:
0
 
iHadiCommented:
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
 
Alpesh PatelAssistant ConsultantCommented:
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
Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

 
nkc1112Author Commented:
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
 
iHadiCommented:
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
 
nkc1112Author Commented:
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
 
iHadiCommented:
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
 
nkc1112Author Commented:
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
 
iHadiCommented:
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
 
nkc1112Author Commented:
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
 
iHadiCommented:
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
 
nkc1112Author Commented:
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
 
iHadiCommented:
replace the:  byte[] buffer = null;
with: byte[] buffer = new byte[bufferSize];
1
 
nkc1112Author Commented:
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
 
iHadiCommented:
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
 
nkc1112Author Commented:
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
 
nkc1112Author Commented:
  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
 
iHadiCommented:
Can you post the string str value after it receives it from the ftp server
0
 
iHadiCommented:
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
 
iHadiCommented:
the ftp list is:  string str = sr.ReadToEnd();
from your code of getting the list of files
0
 
nkc1112Author Commented:
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
 
nkc1112Author Commented:
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
 
nkc1112Author Commented:
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
 
nkc1112Author Commented:
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
 
nkc1112Author Commented:
Following is the error:

Cannot access a disposed object.
Object name: 'System.Net.Sockets.NetworkStream'.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Introducing Cloud Class® training courses

Tech changes fast. You can learn faster. That’s why we’re bringing professional training courses to Experts Exchange. With a subscription, you can access all the Cloud Class® courses to expand your education, prep for certifications, and get top-notch instructions.

  • 13
  • 10
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now