File Retrieved via FtpWebRequest Is Different Than Source File On Server

792 Views Asked by At

I am retrieving GZip files from an FTP server using example code exactly as provided in a Microsoft help page:

https://msdn.microsoft.com/en-us/library/ms229711(v=vs.110).aspx

The code works great! The connection is established, the file is retrieved and saved into my target path.

The problem is that the file created by this code is not the same as the file on the source FTP site. As an example, I may have a source file that is 288,936 bytes, but the file created by this code is 532,550 bytes. Maybe that would be fine if we were dealing with plain text files, but since these are GZip files I am not able to unzip them because they are corrupted, yielding the following error:

The magic number in GZip header is not correct. Make sure you are passing in a GZip stream.

I KNOW this is an error somewhere in this FTP Download code because I can use a different FTP Client to download the file and upzip the file correctly.

Here is the exact source code. I have created my own "helper" methods to make a connection to an FTP server and download a remote file to a local folder destination.

    public static void TransferFileFromFtp(string uri, string username, string password, string folderName, string fileName, DirectoryInfo importFolder)
    {
        FtpWebRequest ftp = GetFtpConnection(uri, username, password, folderName + "/" + fileName);
        ftp.KeepAlive = false;
        ftp.Method = WebRequestMethods.Ftp.DownloadFile;
        FtpWebResponse response = (FtpWebResponse)ftp.GetResponse();

        Stream responseStream = response.GetResponseStream();
        StreamReader reader = new StreamReader(responseStream);

        FileInfo file = new FileInfo(Path.Combine(importFolder.FullName, fileName));
        using (Stream fileStream = file.OpenWrite())
        using (StreamWriter fileWriter = new StreamWriter(fileStream))
        {
            fileWriter.Write(reader.ReadToEnd());
        }

        reader.Close();
        response.Close();
    }


    //Helper method to create an FTP connection...
    private static FtpWebRequest GetFtpConnection(string uri, string username, string password, string folderName)
    {
        FtpWebRequest ftp;

        if (folderName == null || folderName.Length == 0) ftp = (FtpWebRequest)FtpWebRequest.Create(uri);
        else ftp = (FtpWebRequest)FtpWebRequest.Create(uri + "/" + folderName);
        ftp.Credentials = new System.Net.NetworkCredential(username, password);

        return ftp;
    }

What am I missing? How can I get an accurate download of my files?

1

There are 1 best solutions below

1
On BEST ANSWER

FtpWebRequest and FtpWebResponse are painful to work with.

System.Net.WebClient is much easier to use for simple downloads.

Here's an example that downloads a GZip file from the SEC's EDGAR FTP site:

using System.Net;
...
var webClient = new WebClient();
webClient.Credentials = new NetworkCredential("anonymous", "[email protected]");
webClient.DownloadFile("ftp://ftp.sec.gov/edgar/daily-index/2012/QTR4/company.20121003.idx.gz", @"c:\temp\destination.gz");

For more advanced FTP operations, the System.Net.FtpClient project on CodePlex is a good choice. It can be easily installed via NuGet.