I need to provide xml file for download around with 6,00,000 records(data may increase) but not allowed to save file on disk. I was facing issue in directly writing xml to stream & then providing for download , so i have first created xml file on disk & writing data to it and trying to read it in byes & provide for download and then delete file from disk. But getting "system.outofmemoryexception" in "Byte[] b = File.ReadAllBytes(filepath);".
Below is my code:
string name = string.Format("{0:yyyyMMddHHmmss}", DateTime.Now);
string filename = "TestFile.xml";
string filepath = ConfigurationManager.AppSettings["XmlFiles"] + "\\" + filename;
DataTable dataTable = dsData.Tables[0];
FileStream fs =new FileStream(filepath, FileMode.Create);
XmlWriterSettings xws = new XmlWriterSettings { OmitXmlDeclaration = true };
using (XmlWriter xmlWriter = XmlWriter.Create(fs,xws))
{
xmlWriter.WriteStartElement("root");
foreach (DataRow dataRow in dataTable.Rows)
{
xmlWriter.WriteStartElement("datanode");
foreach (DataColumn dataColumn in dataTable.Columns)
{
xmlWriter.WriteElementString(dataColumn.ColumnName.Replace("\n\r", " ")
.Replace("\n", " ").Replace("\r", " "), Convert.ToString(dataRow[dataColumn]).Replace("\n\r", " ").Replace("\n", " ").Replace("\r", " "));
}
xmlWriter.WriteEndElement();
}
xmlWriter.WriteEndElement();
xmlWriter.Flush();
xmlWriter.Close();
}
fs.Close();
Byte[] b = File.ReadAllBytes(filepath);
if (File.Exists(filepath))
File.Delete(filepath);
string s = string.Format("{0:yyyyMMddHHmmss}", DateTime.Now);
HttpContext.Current.Response.ContentType = "application/xml";
HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.UTF8;
HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment; filename=" + s + ".xml" + "");
HttpContext.Current.Response.BinaryWrite(b);
HttpContext.Current.Response.End();
Is there any other way to handle large number of records?
You can directly hookup the XmlWriter to the Response OutputStream without the need for an intermediate file. By setting BufferOutput to false
you prevent that the complete repsonse is buffered server side before being send to the client.
Do notice that the multiple Replace statements will lead to extra memory pressure/more strings to be GC-ed.
string name = string.Format("attachment; filename={0:yyyyMMddHHmmss}.xml", DateTime.Now);
HttpContext.Current.Response.ContentType = "application/xml";
HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.UTF8;
HttpContext.Current.Response.BufferOutput = false; //start streaming immideately
HttpContext.Current.Response.AppendHeader("Content-Disposition", name);
DataTable dataTable = dsData.Tables[0];
XmlWriterSettings xws = new XmlWriterSettings { OmitXmlDeclaration = true };
using (XmlWriter xmlWriter = XmlWriter.Create(
HttpContext.Current.Response.OutputStream, // The OutputStream of the HttpResponse
xws))
{
xmlWriter.WriteStartElement("root");
var cleanedColNames = new Dictionary<DataColumn, string>();
foreach (DataColumn dataColumn in dataTable.Columns)
{
cleanedColNames.Add(dataColumn,
dataColumn.ColumnName.Replace("\n\r", " ")
.Replace("\n", " ")
.Replace("\r", " "));
}
foreach (DataRow dataRow in dataTable.Rows)
{
xmlWriter.WriteStartElement("datanode");
foreach (DataColumn dataColumn in dataTable.Columns)
{
xmlWriter.WriteElementString(
cleanedColNames[dataColumn],
Convert.ToString(dataRow[dataColumn]).Replace("\n\r", " ")
.Replace("\n", " ")
.Replace("\r", " "));
}
xmlWriter.WriteEndElement();
}
xmlWriter.WriteEndElement();
xmlWriter.Flush();
xmlWriter.Close();
}
HttpContext.Current.Response.End();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With