Scott 混合理论
Scott 混合理论

Reputation: 2332

asp.net mvc generate data to download file

public ActionResult GetFile(string dateStr, string serverName, string foodName)
{
        using (var memoStream = new MemoryStream(1024 * 5))
        {
            using (StreamWriter writer = new StreamWriter(memoStream))
            {
                var dataFilter = new CapacityDataFilter(dateStr, serverName, feedName);
                dataFilter.FilterDataByServerAndFeed();
                writer.WriteLine("Feed, StreamMin, TotalMsgNumber, TotalMsgSize, PeakRateMsgNumber, PeakRateMsgSize");

                foreach (var element in dataFilter.DataInTheDay)
                {
                    writer.WriteLine(string.Format("{0},{1},{2},{3},{4},{5}",
                            element.Feed, element.StreamMin,
                            element.TotalMsgNumber, element.TotalMsgSize,
                            element.PeakRateMsgNumber, element.PeakRateMsgSize));
                }


                return File(memoStream, "text/csv", fileName);
            }
        }
}

Exception Details: System.ObjectDisposedException: Cannot access a closed Stream.

this action doesn't work, how to make a download action?

Upvotes: 2

Views: 3983

Answers (1)

Alexei Levenkov
Alexei Levenkov

Reputation: 100547

"this action not work" is wrong way to explain problems...

But in this case you are lucky: you are trying to send incomplete data in memory stream that is seeked to the end, and as second issue stream will be disposed by the time File action actually executes.

The best fix is to move code outisde inner using and return new MemoryStream on buffer of old stream:

using (var memoStream = new MemoryStream(1024 * 5)) 
{ 
   using (StreamWriter writer = new StreamWriter(memoStream)) 
   { 
...
   }
   return File(
      new MemoryStream(memoStream.GetBuffer(), memoStream.length),
      "text/csv", fileName); 
}

Flush + Seek as proposed by armen.shimoon would work too in other cases when you are using stream immediately:

writer.Flush();
memoStream.Flush();
memoStream.Position = 0;    
// do something with MemoryStream right here before either of `using`ends.

Upvotes: 5

Related Questions