title: Downloading Large Files Using MVC
body: <p>I have an MVC 5 application with Entity Framework behind it. I am implementing an export functionality to export user's data. The user can select records and click export, and expect a file to get downloaded in the form of HTML.</p>
  
  <p>Now I have got the process working for small number of records but it won't work as the file grows. I believe there has to be a way for the app to stream the result rather than constructing it the way I am. I explain:</p>
  
  <p>In the view I do something like:</p>
  
  <pre><code>@using (Html.BeginForm("ExportRecords", "UserData", FormMethod.Post))
  {
      @Html.AntiForgeryToken()
      @Html.Hidden("selectedRecordIds", "1;2;3;4")
      &lt;input id="submit" name="submit" type="submit" /&gt;
  }
  </code></pre>
  
  <p>In the controller, I get the records from DB+Azure, and generate HTML and kick off the download:</p>
  
  <pre><code>[ValidateAntiForgeryToken]
  public async Task&lt;ActionResult&gt; ExportRecords(string selectedRecordIds)
  {
      var selectedRecordsIdList = selectedRecordIds.Split(";".ToCharArray()).ToList();
  
      var records = await GetRecords(selectedRecordsIdList);
  
      var recordsAsHtml = await Helper.GenerateHtml(records);
  
      return File(Encoding.ASCII.GetBytes(recordsAsHtml),System.Net.Mime.MediaTypeNames.Application.Octet, "ExportedFile.html");}
  </code></pre>
  
  <p>Now the cut-down version of GenerateHtml method looks like:</p>
  
  <pre><code>public static async Task&lt;string&gt; GenerateHtml(List&lt;Records&gt; records)
  {
      var stringWriter = new StringWriter();
      using (var writer = new HtmlTextWriter(stringWriter))
      {
          foreach (var record in records)
          {
             writer.Indent++; 
             writer.Write("&lt;tr&gt;");
             writer.WriteLine();
              ......
          }
      }
  
      // This could cause "Out of Memory Exception"
      var htmlContent = stringWriter.ToString();
  
      return htmlContent;
  }
  </code></pre>
  
  <p>So using the above, I put some for loop around the foreach to simulate a scenario where there are thousands of records, and pretty soon I was getting Out of Memory Exception. </p>
  
  <p>So what is the best way to export large amount of data?</p>
  
  <p>Thank you for any help.</p>