c# - 尝试下载单词时出现无法访问关闭的流之类的错误
问题描述
当我单击视图中的按钮时,我正在使用以下代码下载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)
解决方案
您正在从您的 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");
推荐阅读
- python - 获取列表以映射到python中的值的解决方法
- php - 我的 Laravel 网站正在将所有帖子请求重定向到索引页面
- azure - 托管标识 Azure 角色分配?
- reactjs - 自定义反应挂钩未获取值
- ubuntu - powertop 估计的 W 文档
- boost - Boost log crash 用一个简单的例子(Linux)
- react-native - 如何在开发中的两个 Expo 应用程序之间建立深度链接?
- sql - 提高选择和插入的性能
- git - 如何在 Flutter 中引用存储库中的包?
- composer-php - Travis CI:为什么作曲家有时会安装整个包,有时不会?