首页 > 解决方案 > 尝试下载单词时出现无法访问关闭的流之类的错误

问题描述

当我单击视图中的按钮时,我正在使用以下代码下载word文档,但有些似乎无法正常工作并出现以下错误:

ObjectDisposedException: Cannot access a closed Stream. System.IO.MemoryStream.Read(byte[] buffer, int offset, int count)

下面是我正在使用的代码

 public IActionResult CreateDocument()
 {
        using (MemoryStream mem = new MemoryStream())
        {
            using (WordprocessingDocument wordDoc = WordprocessingDocument.Create(mem, WordprocessingDocumentType.Document))
            {
                var mainDocumentPart = wordDoc.AddMainDocumentPart();
                Body body = new Body();
                mainDocumentPart.Document = new Document(body);
                Document doc = new Document();

                /// Add header
                ApplyHeader(wordDoc);
                List<string> bulletedList = new List<string>() { "This is bulleted point 1", "This is bulleted point 2", "This is bulleted point 3" };
                var runList = ListOfStringToRunList(bulletedList);

                // Add buletted points
                ApplyBulletedList(wordDoc, body, doc, runList);

                string xmlFile = @"Resources\movies.xml";
                string moviesXml = System.IO.File.ReadAllText(xmlFile);
                XElement movies = XElement.Parse(moviesXml);

               TransformMovies(movies,body);

                wordDoc.MainDocumentPart.Document = doc;
                return File(mem, "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "ABC.docx");
            }

        }
 }

以下是 index.cshtml 文件的代码

     @{
    Html.BeginForm("CreateDocument", "Home", FormMethod.Get);
    {
        <div>
            <input type="submit" value="Create Document" style="width:150px;height:27px" />
        </div>
    }
    Html.EndForm();
   }

我不确定我在哪里使用此代码进行操作,并且我正在使用 dot net core 有人请让我知道如何避免提到的错误,并且当我单击按钮时需要能够下载 word 文档。

提前谢谢了

堆栈跟踪

ObjectDisposedException: Cannot access a closed Stream.
System.IO.MemoryStream.Read(byte[] buffer, int offset, int count)
System.IO.MemoryStream.ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
Microsoft.AspNetCore.Http.StreamCopyOperationInternal.CopyToAsync(Stream source, Stream destination, Nullable<long> count, int bufferSize, CancellationToken cancel)
Microsoft.AspNetCore.Mvc.Infrastructure.FileResultExecutorBase.WriteFileAsync(HttpContext context, Stream fileStream, RangeItemHeaderValue range, long rangeLength)
Microsoft.AspNetCore.Mvc.Infrastructure.FileStreamResultExecutor.ExecuteAsync(ActionContext context, FileStreamResult result)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeResultAsync>g__Logged|21_0(ResourceInvoker invoker, IActionResult result)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|29_0<TFilter, TFilterAsync>(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext<TFilter, TFilterAsync>(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

标签: c#.netmemory.net-coreasp.net-core-mvc

解决方案


您正在从您的 using 内部返回 mem,此时它已被处理。

此 File() 中的“mem”变量超出范围,并在您返回它时立即被释放。

return File(mem, "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "ABC.docx");

例如,在下面,Console.Writeline 将抛出“无法访问已关闭的流”。

class Program
{
    static MemoryStream GetMemoryStream()
    {
        using (MemoryStream mem = new MemoryStream())
        {
            // BAD CODE - BUG!
            return mem;

            // The above will return an object which is about to be Disposed!
        }
    }
    static void Main(string[] args)
    {
        MemoryStream mem = GetMemoryStream();

        Console.WriteLine(mem.Length);
    }
}

像下面这样的东西会起作用,这会保持使用情况,因为在返回上方抛出异常。如果返回成功,您将需要在将来的某个时间手动 Dispose newMem。

        var newMem = new MemoryStream();
        mem.CopyTo(newMem);
        return File(newMem, "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "ABC.docx");

推荐阅读