在生产机器 ASP.Net 上使用 FtpWebRequest 从 ftp 服务器流式传输和保存文件时的行为不同

本文关键字:保存文件 传输 服务器 ftp ASP 机器 Net FtpWebRequest | 更新日期: 2023-09-27 17:56:44

这个问题

可能有一些非常简单的答案,但我真的坚持在这个问题上。

我编写了一些代码,通过ftp获取相当大的(4GB +)xml文件,将其读取为字符串并将文档拆分为较小的部分。最后,较小的文件被写入光盘。

在我的开发人员机器上一切运行良好,但是当投入生产时,脚本在读取了十分之一的文件后突然结束。不会引发任何异常。每一行代码都按预期执行。 它只是在浏览整个文件之前结束。这让我认为需要篡改的是一些IIS或web.config设置。

代码作为自定义用户控件在 Umbraco CMS 内运行。服务器是运行IIS的2008年Windows机器。

有什么想法吗? 这是代码:

FtpWebRequest request = (FtpWebRequest)WebRequest.Create(serverUri);
    request.Credentials = new NetworkCredential("anonymous", "x@y.z");
    request.Method = WebRequestMethods.Ftp.DownloadFile;
    request.Timeout = -1;
    request.KeepAlive = true;
    request.UsePassive = true;
    request.UseBinary = true;
    using (response = (FtpWebResponse)request.GetResponse())
    using (responseStream = response.GetResponseStream())
    using (StreamReader sr = new StreamReader(responseStream))
    {
      ReadStreamIntoNewRecord(fileName, sr, ref progress, ref result);
    }

ReadStreamIntoNewRecord 函数如下所示:

private void ReadStreamIntoNewRecord(string fileName, StreamReader sr, int NumberOfRecordsPerBatch)
{
    string line = "";
    string record = "";
    int i = 0;  
    XDocument xdoc = new XDocument(new XElement("collection"));
    while (sr.Peek() >= 0)
    {
        line = sr.ReadLine();
        if (line.Contains("</record>"))
        {
            xdoc.Element("collection").Add(MakeRecordFromString(record + line));
            record = "";
            i++;
            if (i % NumberOfRecordsPerBatch == 0)
            {
                SaveRecordToFile(fileName, xdoc);
                xdoc = new XDocument(new XElement("collection"));
            }
        }
        else
        {
            record = record + line;
        }
    }
    SaveRecordToFile(fileName, xdoc);            
}

在生产机器 ASP.Net 上使用 FtpWebRequest 从 ftp 服务器流式传输和保存文件时的行为不同

哇,将 4GB 文件加载到内存中的字符串中是一个可怕的想法。 如果磁盘上的 UTF-8 为 4GB,那么内存中的内存为 8GB,因为内存中的所有 .NE 字符串都是 UTF-16。 幸运的是,你并没有真正这样做,你只是说你在描述中。

我相信你应该稍微改变一下 while 循环。 如前所述,当确实有更多的数据进入时,它可以检测到不正确的流结束。 请改用这个:

while ((line = sr.ReadLine()) != null)
{
    ...
}

除此之外,最好使用简单的StreamWriterXmlTextWriter来保存文件而不是XDocumentXDocument 将整个文件保存在内存中,旨在更轻松地使用 Linq-to-XML 进行遍历。 您没有使用它,并且可以从更轻的重量级中受益。