EPPlus无法访问已关闭的流。

3
为什么在ASP.NET MVC应用程序中,使用MemoryStream写入数据并将位置定位到零后,EPPlus会抛出“System.ObjectDisposedException: Cannot access a closed Stream.”的异常?
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",
        };
    }
}

如果我将var memoryStream = ...移出using语句,那么它可以工作,但是如果没有显式释放内存,则在下一次垃圾回收之前,这可能会泄漏大量内存,感觉不太好。也许ExcelPackage也会处理MemoryStream的释放?

完整堆栈跟踪:

[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

你能发布完整的堆栈跟踪吗?异常发生在哪里? - Jim Bolla
1个回答

4
我认为是因为你的MemoryStream已经被using使用过了。
这会导致(在处理结束时)流被关闭和释放。
FileStreamResult负责关闭它,然后删除using

是的,问题解决了。根据这个答案FileStreamResult确实关闭了流。 - Petrus Theron

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接