Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EPPlus cannot access a closed Stream

Why does EPPlus throw System.ObjectDisposedException: Cannot access a closed Stream. after writing to a MemoryStream and seeking to position zero in an ASP.NET MVC application?

public FileStreamResult ExportToExcel()
{
    using (var memoryStream = new MemoryStream())
    using (var excel = new ExcelPackage())
    {
        var worksheet = excel.Workbook.Worksheets.Add("Products");
        worksheet.Cells["A1"].LoadFromCollection(Collection: myCollection, PrintHeaders: true);
        excel.SaveAs(memoryStream);
        memoryStream.Seek(0, SeekOrigin.Begin); // also tried memoryStream.Position = 0;

        return new FileStreamResult(memoryStream, contentType)
        {
            FileDownloadName = "test.xlsx",
        };
    }
}

If I move the var memoryStream = ... out of the using statement, it works, but it feels like this could leak a lot of memory for large results until the next garbage collection, if it is not disposed of explicitly. Maybe the ExcelPackage disposes the MemoryStream as well?

Full Stack Trace:

[ObjectDisposedException: Cannot access a closed Stream.]
   System.IO.__Error.StreamIsClosed() +57
   System.IO.MemoryStream.Read(Byte[] buffer, Int32 offset, Int32 count) +10653946
   System.Web.Mvc.FileStreamResult.WriteFile(HttpResponseBase response) +80
   System.Web.Mvc.FileResult.ExecuteResult(ControllerContext context) +168
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) +13
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +56
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +420
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +420
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) +52
   System.Web.Mvc.Async.<>c__DisplayClass28.<BeginInvokeAction>b__19() +173
   System.Web.Mvc.Async.<>c__DisplayClass1e.<BeginInvokeAction>b__1b(IAsyncResult asyncResult) +100
   System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +27
   System.Web.Mvc.Controller.<BeginExecuteCore>b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +13
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +36
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +54
   System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +39
   System.Web.Mvc.Controller.<BeginExecute>b__15(IAsyncResult asyncResult, Controller controller) +12
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +28
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +54
   System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +29
   System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +10
   System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__4(IAsyncResult asyncResult, ProcessRequestState innerState) +21
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +36
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +54
   System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +31
   System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +9629296
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155
like image 635
Petrus Theron Avatar asked Jan 23 '26 13:01

Petrus Theron


1 Answers

I think it is because you have your MemoryStream is a using.

This causes (at the end of processing) the stream to be closed and disposed.

Let the FileStreamResult handle closing this, and remove the using.

like image 75
Patrick Hofman Avatar answered Jan 26 '26 01:01

Patrick Hofman