0

我有一些内部使用的实用程序类,它从 FTP 服务器下载文件。过去,所有这些都是纯文本文件,并且可以正常工作。但是,我们现在有一些我想要下载的压缩文件。当此文件在本地写入时,大小从 ~80 Kb 变为 ~140 Kb。为什么文件在写入过程中损坏?为什么这不适用于普通文本文件?要使此代码适用于所有文件类型,需要进行哪些更改?

        private static string GetFile(string file, bool inBound)
        {
            string path;
            if (inBound)
                path = Config.settings["FTPIn"] + file;
            else
                path = Config.settings["FTPOut"] + file;

            FtpWebRequest request = (FtpWebRequest)WebRequest.Create(path);
            request.Method = WebRequestMethods.Ftp.DownloadFile;

            request.Credentials = new NetworkCredential(Config.Settings["FTPUser"], Config.Settings["FTPPass"]);
            FtpWebResponse response = (FtpWebResponse)request.GetResponse();
            string file_contents = System.String.Empty;

            using (Stream responseStream = response.GetResponseStream())
            {
                using (StreamReader reader = new StreamReader(responseStream))
                {

                    try
                    {

                        file_contents = reader.ReadToEnd();
                    }
                    catch (Exception e)
                    {
                        ResultLogger.LogVerbose(trGuid, "Exception while getting file from FTP share.");
                        ResultLogger.LogVerbose(trGuid, e.Message);
                        ResultLogger.LogVerbose(trGuid, e.StackTrace);
                    }
                    reader.Close();
                    response.Close();
                }
            }

            return file_contents;

        }

请注意,没有运行时错误(至少在其他一些代码尝试解压缩文件之前不会),文件只是在写入过程中被损坏。

另外,调用代码如下;

      string file_contents = GetFile(fileName, inBound);
      File.WriteAllText(@".\" + fileName, file_contents);
      return new FileInfo(@".\" + fileName);
4

2 回答 2

1

您不想将原始数据读入字符串,而应该将其读入字节数组。.NET 字符串由两字节字符组成。

您应该使用 a BinaryReader,或者更好的是,将其直接写入文件,而不是先将其读入内存,使用CopyTo()

private static void GetFile(string file, bool inBound)
{
    // Removed the FTP setup code

    using (Stream responseStream = response.GetResponseStream())
    {
        using (Stream outputStream = File.OpenWrite(@".\" + file))
        {
            try
            {
                responseStream.CopyTo(outputStream);
            }
            catch (Exception e)
            {
                // Removed Exception code
            }
        }
    }
}
于 2013-10-01T17:57:08.523 回答
0

request.UseBinary = true;你的问题是下载二进制文件时需要设置。否则,FTP 流会将无效的二进制值转换为有效的字符串值以通过线路发送。这就是导致下载时文件大小增加以及“损坏”文件的原因,因为您目前没有考虑到这种差异。代码应如下所示:

更新:我刚刚注意到您也将它作为字符串返回。我修改了代码以正确读取和填充缓冲区以返回二进制文件。

    private static byte[] GetFile(string file, bool inBound)
{
    string path;
    if (inBound)
        path = Config.settings["FTPIn"] + file;
    else
        path = Config.settings["FTPOut"] + file;

    FtpWebRequest request = (FtpWebRequest)WebRequest.Create(path);
    request.Method = WebRequestMethods.Ftp.DownloadFile;
    request.UseBinary = true;

    request.Credentials = new NetworkCredential(Config.Settings["FTPUser"], Config.Settings["FTPPass"]);
    FtpWebResponse response = (FtpWebResponse)request.GetResponse();
    byte[] file_contents = null;

    using (Stream responseStream = response.GetResponseStream())
    {
        byte[] buffer = new byte[2048];
        using (MemoryStream ms = new MemoryStream())
        {
            int readCount = responseStream.Read(buffer, 0, buffer.Length);
            while (readCount > 0)
            {
                ms.Write(Buffer, 0, readCount);
                readCount = responseStream.Read(buffer, 0, buffer.Length);
            }

            file_contents = ms.ToArray();
        }
    }

    return file_contents;
}
于 2013-10-01T17:52:18.233 回答