【问题标题】:Error while copying content to a stream.?将内容复制到流时出错。?
【发布时间】:2019-04-01 09:56:01
【问题描述】:

我正在使用 WebApi 导出 excel 文件,但它会引发异常,我不知道为什么。我用谷歌搜索了它,但没有找到任何解决方案。

例外:

    <Error>
    <Message>An error has occurred.</Message>
    <ExceptionMessage>Error while copying content to a stream.</ExceptionMessage>
    <ExceptionType>System.Net.Http.HttpRequestException</ExceptionType>
    <StackTrace>
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Microsoft.AspNet.WebApi.Extensions.Compression.Server.BaseServerCompressionHandler.<HandleCompression>d__17.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult() at Microsoft.AspNet.WebApi.Extensions.Compression.Server.BaseServerCompressionHandler.<SendAsync>d__15.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at System.Web.Http.HttpServer.<SendAsync>d__0.MoveNext()
    </StackTrace>
    <InnerException>
    <Message>An error has occurred.</Message>
    <ExceptionMessage>Cannot access a closed Stream.</ExceptionMessage>
    <ExceptionType>System.ObjectDisposedException</ExceptionType>
    <StackTrace>
    at System.IO.__Error.StreamIsClosed() at System.IO.MemoryStream.get_Position() at System.Net.Http.StreamToStreamCopy.StartAsync()
    </StackTrace>
    </InnerException>
    </Error>

我的代码是:

[AllowAnonymous]
[HttpGet]
[Route("api/AddPatient/ExportToExcel")]
public HttpResponseMessage ExportToExcel()
{
    try
    {
        MemoryStream dataStream = Utility.GetFile();

        HttpResponseMessage httpResponseMessage = Request.CreateResponse(HttpStatusCode.OK);
        httpResponseMessage.Content = new StreamContent(dataStream);
        httpResponseMessage.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
        httpResponseMessage.Content.Headers.ContentDisposition.FileName = "Test.xlsx";
        httpResponseMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");

        return httpResponseMessage;
    }
    catch (Exception ex)
    {
        throw;
    }
}  

GetFile函数如下获取excel内存流 注意:使用 NPOI 我正在创建 excel 文件

public static MemoryStream GetFile()
        {
            MemoryStream stream =null;
            XSSFWorkbook wb = new XSSFWorkbook();
            ISheet sheet = wb.CreateSheet("Test");
            var row = sheet.CreateRow(0);
            var cell = row.CreateCell(0);
            cell.SetCellValue("Test");

            using ( stream = new MemoryStream())
            {
                wb.Write(stream);    
            } 

            return stream;
        }

【问题讨论】:

  • Utility.GetFile好像出错了,请粘贴一下。
  • 如果你只是重新抛出异常,那么设置try catch 是没有意义的......
  • 您要处理 stream然后返回它?然后你得到ObjectDisposedException?不太确定这里的问题是什么。
  • Utility.GetFile() 是做什么的?它是在内存中创建文件还是从磁盘创建文件?在任何情况下,您都可以使用return File(...) 返回存储的文件或流。 MemoryStream 只不过是 byte[] 数组的包装器,处理它不会释放任何资源

标签: c# asp.net-mvc asynchronous asp.net-web-api


【解决方案1】:

在处理流对象时需要小心。

但我认为您获取dataStream 的功能也有误。也许更多代码?

try
{
    using(MemoryStream dataStream = Utility.GetFile())
    {
      // read from beginning 
      dataStream.Position = 0;

      HttpResponseMessage httpResponseMessage = Request.CreateResponse(HttpStatusCode.OK);
      httpResponseMessage.Content = new StreamContent(dataStream);
      httpResponseMessage.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
      httpResponseMessage.Content.Headers.ContentDisposition.FileName = "Test.xlsx";
      httpResponseMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");

      return httpResponseMessage;
    }
}
catch (Exception ex)
{
    throw;
}

您的GetFile 无法包装 using 语句,这将关闭您的内存流对象。

 // try this
 public static MemoryStream GetFile()
    {
        MemoryStream stream = new MemoryStream();
        // do your thing
        XSSFWorkbook wb = new XSSFWorkbook();
        ISheet sheet = wb.CreateSheet("Test");
        var row = sheet.CreateRow(0);
        var cell = row.CreateCell(0);
        cell.SetCellValue("Test");

        wb.Write(stream);    
        // reset position here
        stream.Position = 0;

        return stream;
    }

【讨论】:

  • 现在出现新错误:无法访问已关闭的流
  • @JasminSolanki 通常这是因为你在它已经“关闭”时访问它,你需要用 using 语句包装,这样你的对象在你想使用它时不会被释放
  • @JasminSolanki 您不能在 getFile 函数中使用 using 语句,这就是您收到相同错误的原因。删除该 using 语句。
  • 是的,我更改了它,但流仍然关闭
  • 为什么使用这段代码而不是简单的return File(stream,..);?实际的解决方法是避免释放 MemoryStream,或者改用 byte[] 缓冲区。 MemoryStream 只不过是一个 byte[] 的包装器
猜你喜欢
  • 2016-01-18
  • 1970-01-01
  • 2021-01-24
  • 2020-04-10
  • 1970-01-01
  • 2018-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多