Archive or image is corrupted after uploading to F

2019-01-20 05:35发布

问题:

I have two methods:

  1. Uploads files to the FTP Server
  2. Downloads Files from the Server.

Everything works perfectly with text or xml files. But when I'm trying to upload and then download an archive or an image I get the "windows cannot open the folder. the compressed zip file is invalid" error for the archives and almost the same for the images. What may be the problem?

Here is the listing of my methods:

Upload:

private string Upload(string Login, string Password, string FilePath, string FileName, string uuid, string FTPDir)
{
    string CreateDirectory = CreateFTPDirectory(Login, Password, uuid, FTPDir);

    FtpWebRequest request = (FtpWebRequest)WebRequest.Create(@"ftp://" + FTPDir + uuid + "/" + FileName);
    request.Method = WebRequestMethods.Ftp.UploadFile;
    request.UseBinary = true;

    StreamReader sourceStream = new StreamReader(FilePath + FileName);
    byte[] fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
    sourceStream.Close();
    request.ContentLength = fileContents.Length;

    using (Stream S = request.GetRequestStream())
    {
        S.Write(fileContents, 0, fileContents.Length);
    }
    FtpWebResponse response = (FtpWebResponse)request.GetResponse();
    response.Close();

    return response.StatusDescription;
}

Download:

private string Download(string Login, string Password, string FileName, string uuid, string FTPDir, string Destination)
{
    FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://" + FTPDir + uuid + "/" + FileName);
    request.UseBinary = true;
    request.Method = WebRequestMethods.Ftp.DownloadFile;
    request.Credentials = new NetworkCredential(Login, Password);
    byte[] buffer = new byte[1024];

    using (var response = (FtpWebResponse)request.GetResponse())
    {

        using (var stream = response.GetResponseStream())
        {
            using (var fs = new FileStream(Destination, FileMode.OpenOrCreate))
            {
                int readCount = stream.Read(buffer, 0, 1024);

                while (readCount > 0)
                {
                    fs.Write(buffer, 0, readCount);
                    readCount = stream.Read(buffer, 0, 1024);                            
                }
            }
            return response.StatusDescription;
        }
    }
}

回答1:

You are uploading a binary file (a bitmap image) as if it were a text file in UTF-8 encoding:

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

That naturally corrupts the file.

You have to transfer binary files exactly as they are, bit by bit.

Moreover your technique is quite inefficient for potentially large image files. You keep whole file in memory at least twice.

The code, that you need, is actually much simpler than yours:

using (Stream fileStream = File.OpenRead(FilePath + FileName)
using (Stream ftpStream = request.GetRequestStream())
{
    fileStream.CopyTo(ftpStream);
}

Your download code is ok, but again, it can be simplified to:

using (Stream ftpStream = request.GetResponse().GetResponseStream())
using (Stream fileStream = File.Create(Destination))
{
    ftpStream.CopyTo(fileStream);
}

For a full code, see Upload and download a binary file to/from FTP server in C#/.NET.