简体   繁体   中英

Provide XML file for download with large number of records in asp.net c#

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();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM