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

C# 在生产机器ASP.Net上使用FtpWebRequest从ftp服务器流式传输和保存文件时的不同行为,c#,asp.net,io,umbraco,ftpwebrequest,C#,Asp.net,Io,Umbraco,Ftpwebrequest,可能有一些非常简单的答案,但我真的被这个问题困住了 我编写了一些代码,通过ftp获取相当大的(4GB+)xml文件,将其作为字符串读取,并将文档拆分为较小的部分。最后,较小的文件被写入光盘 在我的开发人员机器上,一切都运行得很好,但是当投入生产时,脚本在只读取了文件的十分之一后突然结束。没有抛出异常。每一行代码都按预期执行。它在浏览整个文件之前就结束了。这让我觉得需要篡改的是某些IIS或web.config设置 代码作为自定义用户控件在Umbraco CMS中运行。服务器是运行IIS的2008

可能有一些非常简单的答案,但我真的被这个问题困住了

我编写了一些代码,通过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);            
}
private void readstreamintowrecord(字符串文件名,StreamReader sr,int NumberOfRecordsPerBatch)
{
字符串行=”;
字符串记录=”;
int i=0;
XDocument xdoc=新XDocument(新XElement(“集合”);
而(sr.Peek()>=0)
{
line=sr.ReadLine();
如果(第行包含(“”))
{
元素(“集合”).Add(MakeRecordFromString(记录+行));
记录=”;
i++;
如果(i%NumberOfRecordsPerBatch==0)
{
SaveRecordToFile(文件名,xdoc);
xdoc=新XDocument(新XElement(“集合”);
}
}
其他的
{
记录=记录+行;
}
}
SaveRecordToFile(文件名,xdoc);
}

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

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

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

除此之外,您最好使用简单的
StreamWriter
XmlTextWriter
来保存文件,而不是
XDocument
XDocument
将整个文件保存在内存中,并设计为使用Linq to Xml更容易地进行遍历。你不使用它,可以受益于更轻的重量类

MakeRecordFromString()函数实际上在将XElement附加到XDocument之前对XElement进行了一些处理,因此它必须是XDocument。您的解决方案工作得更好。不过,我不得不添加一个try/catch语句,因为您的表达式抛出了一个表示无法访问已处置对象的异常。该异常不影响代码中的功能。我想知道为什么我的解决方案表现不同。相同的代码,相同的数据被解析,代码在不同的计算机上运行。