Search code examples
c#serverftpupload

Files uploaded to ftp server, corrupted why?


Files are uploading successfully but with corrupted files. Kindly check my code and fix my problem. I think my problem in this line:

 byte[] fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());;
string ftpurl = "ftp://IP";
            string ftpusername = "u09z0fyuu"; // e.g. username
            string ftppassword = "Yamankatita1@"; // e.g. password

            string PureFileName = new FileInfo(file_name).Name;
            String uploadUrl = String.Format("{0}/{1}/{2}", ftpurl, "PDPix", file_name);
            FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(uploadUrl);
            request.Method = WebRequestMethods.Ftp.UploadFile;
            // This example assumes the FTP site uses anonymous logon.  
            request.Credentials = new NetworkCredential(ftpusername, ftppassword);
            request.Proxy = null;
            request.KeepAlive = true;
            request.UseBinary = true;
            request.UsePassive = true;
            request.Method = WebRequestMethods.Ftp.UploadFile;

            // Copy the contents of the file to the request stream.  
            StreamReader sourceStream = new StreamReader(_mediaFile.Path);
            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();
            _ = DisplayAlert("Upload File Complete, status {0}", response.StatusDescription,"OK");

Solution

  • You've said you're trying to upload image files. You can't treat these as UTF8 because they are binary data and they are not encoded with UTF8. You need to treat binary data as binary data.

    You can read the bytes directly:

    byte[] fileContents = File.ReadAllBytes(_mediaFile.Path);
    

    Explanation

    UTF8 can't represent all possible values of a byte (0x00 - 0xFF) as characters and roundtrip them back to a binary format again. We can observe this with the following code:

    byte[] input = new byte[8];
    RNGCryptoServiceProvider.Create().GetBytes(input);
    
    Console.WriteLine(string.Join(", ", input.Select(i => i)));
    
    string tmp = System.Text.Encoding.UTF8.GetString(input); // interpret arbitrary bianry data as text
    // the data is corrupted by this point
    byte[] result = System.Text.Encoding.UTF8.GetBytes(tmp); // convert the text back to a binary form (utf8-encoded)
    Console.WriteLine(string.Join(", ", result.Select(i => i)));
    

    Try it online

    Here we generate 8 random bytes, print their values, try to interpret them as a string, convert that string back to bytes, and print their new values.

    For the following 8 bytes:

    16, 211, 7, 253, 207, 91, 24, 137
    

    We got the following bytes as a result:

    16, 239, 191, 189, 7, 239, 191, 189, 239, 191, 189, 91, 24, 239, 191, 189
    

    And just like that, our data is corrupted! Long story short: don't use text encoding for binary data.