C# 在生产机器ASP.Net上使用FtpWebRequest从ftp服务器流式传输和保存文件时的不同行为
可能有一些非常简单的答案,但我真的被这个问题困住了 我编写了一些代码,通过ftp获取相当大的(4GB+)xml文件,将其作为字符串读取,并将文档拆分为较小的部分。最后,较小的文件被写入光盘 在我的开发人员机器上,一切都运行得很好,但是当投入生产时,脚本在只读取了文件的十分之一后突然结束。没有抛出异常。每一行代码都按预期执行。它在浏览整个文件之前就结束了。这让我觉得需要篡改的是某些IIS或web.config设置 代码作为自定义用户控件在Umbraco CMS中运行。服务器是运行IIS的2008 Windows计算机 有什么想法吗?代码如下: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
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语句,因为您的表达式抛出了一个表示无法访问已处置对象的异常。该异常不影响代码中的功能。我想知道为什么我的解决方案表现不同。相同的代码,相同的数据被解析,代码在不同的计算机上运行。