【问题标题】:Size of zip increases when downloading with FtpWebRequest使用 FtpWebRequest 下载时,zip 的大小会增加
【发布时间】:2013-10-01 17:29:28
【问题描述】:

我有一些内部使用的实用程序类,它从 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);

【问题讨论】:

    标签: c# .net file-io ftpwebrequest


    【解决方案1】:

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

    您应该使用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
                }
            }
        }
    }
    

    【讨论】:

    • 我必须参加一个会议,但我会在今天晚些时候有空的时候尝试一下。我觉得它会解决我的问题。
    【解决方案2】:

    你的问题是下载二进制文件时需要设置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;
    }
    

    【讨论】:

    • 这并没有解决问题。我认为这可能是朝着正确方向迈出的一步,但我认为我需要更改所有文件处理代码以使用字节流/数组而不是字符串或类似的东西。这个问题stackoverflow.com/questions/3196226/… 给我的印象是问题可能是由于将文件内容存储为字符串然后写入该字符串。此外,这将如何影响非二进制文件的处理?需要有条件吗?
    • @evanmcdonnal 您必须知道要下载的文件类型(二进制或非二进制),然后调用适当的方法来执行此操作。此时最好直接保存到文件系统,而不是从方法返回数据,或者将这两种方法都视为返回字节数组。
    猜你喜欢
    • 2018-08-02
    • 2011-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-13
    • 2014-08-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多