12

I am trying to upload a zip file to server using C# (Framework 4)and following is my code.

string ftpUrl = ConfigurationManager.AppSettings["ftpAddress"];
string ftpUsername = ConfigurationManager.AppSettings["ftpUsername"];
string ftpPassword = ConfigurationManager.AppSettings["ftpPassword"];  
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftpUrl + "Transactions.zip");  
request.Proxy = new WebProxy(); //-----The requested FTP command is not supported when using HTTP proxy.
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential(ftpUsername, ftpPassword);
StreamReader sourceStream = new StreamReader(fileToBeUploaded);
byte[] fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
sourceStream.Close();
request.ContentLength = fileContents.Length;
Stream requestStream = request.GetRequestStream();
requestStream.Write(fileContents, 0, fileContents.Length);
requestStream.Close();
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
Console.WriteLine("Upload File Complete, status {0}", response.StatusDescription);
            response.Close();  

The zip file is uploaded successfully, but when I tried to open the zip file from server(manually), it showed me Unexpected end of archive error.
For file compression I am using Ionic.zip dll. Before transferring the zip file, I was able to extract successfully.

Any help appreciated. Thanks.

davmos
  • 9,324
  • 4
  • 40
  • 43
Praveen
  • 55,303
  • 33
  • 133
  • 164

1 Answers1

21

This is the problem:

StreamReader sourceStream = new StreamReader(fileToBeUploaded);
byte[] fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());

StreamReader (and any TextReader) is for text data. A zip file isn't text data.

Just use:

byte[] fileContents = File.ReadAllBytes(fileToBeUploaded);

That way you're not treating binary data as text, so it shouldn't get corrupted.

Or alternatively, don't load it all into memory separately - just stream the data:

using (var requestStream = request.GetRequestStream())
{
    using (var input = File.OpenRead(fileToBeUploaded))
    {
        input.CopyTo(requestStream);
    }
}

Also note that you should be using using statements for all of these streams, rather than just calling Close - that way the resources will be disposed even if an exception is thrown.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Is there any way to know whether our file is uploaded successfully or not, like `status.code =OK`? – Praveen May 22 '13 at 09:04
  • 1
    @user1671639: Yes - get the status code from the `FtpWebResponse` and see whether it's `CommandOK` or `FileActionOK`. (There may be some others to look for - experiment with it.) I'd expect it to throw an exception when you get the response if it's failed, to be honest. – Jon Skeet May 22 '13 at 10:49
  • I tried specifying `FtpWebResponse response = (FtpWebResponse)request.GetResponse();` and I got it from `response.StatusDescription = "226 File receive OK."`. But I am already using `using` statement as you advised. Does this affect my program? – Praveen May 22 '13 at 13:46
  • 1
    @user1671639: I don't know what you mean. Yes, you should use a `using` statement for the response... but I'd advise using the status *code* rather than the description. – Jon Skeet May 22 '13 at 14:30
  • I have "*.bin" which is getting corrupt. I tried your way ,but its not helping.Any help or guess.Thanks – KumarHarsh Oct 10 '18 at 04:49
  • @KumarHarsh: No, there isn't nearly enough information for me to help you based on that. – Jon Skeet Oct 10 '18 at 06:10
  • @JonSkeet ,my answer is below .Can I by any chance recover those corrupted files ?I HTTP PUT those file in IIS WEDAV folder using below code – KumarHarsh Oct 18 '18 at 19:22