将MemoryStream转换为Array时出现OutOfMemory异常

时间:2016-12-08 09:57:26

标签: c# arrays exception out-of-memory memorystream

我使用以下代码在HttpResponseMessage中返回一个字节数组:

using (WebResponse response = (HttpWebResponse)request.GetResponse())
{
   byte[] bytes = ReadFully(response.GetResponseStream());
   ......
}
public static byte[] ReadFully(Stream input)
{
  byte[] buffer = new byte[16*1024];
  using (MemoryStream ms = new MemoryStream())
  {
    int read;
    while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
    {
        ms.Write(buffer, 0, read);
    }
    return ms.ToArray(); // This line throws OutOfMemory exception
  }
}

在上一个OutOfMemory语句中抛出了return ms.ToArray()异常。

我需要将结果byte[]设置为HttpResponseMessage.Content

2 个答案:

答案 0 :(得分:2)

您应该直接返回流,而不是先将其读入内存。

public HttpResponseMessage CreateMessage(Stream input)
{
    HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
    result.Content = new StreamContent(input);
    return result;
}

不要忘记设置适当的标题等。

修改

  

...我需要将HttpResponseMessage中的字节数组写入文件

根据您的上一条评论,您更改了自己的问题,并希望采用其他方式。以下是从Web响应写入文件的示例。

public void writetoFile(HttpWebResponse response)
{
    var inStream = response.GetResponseStream();
    using (var file = System.IO.File.OpenWrite("your file path here"))
    {
        inStream.CopyTo(file);
    }
}

答案 1 :(得分:1)

Igor发布了解决方案,以及处理流内容的正确方法。使用其中一个MVC辅助函数(如File(stream,contentype))或类StreamContent等类将流内容直接发送到客户端,例如:

return File(myStream,myExcelContentTypeString);

return File(myStream,myExcelContentTypeString,"ReallyBigFile.xlsx");

错误的原因是OOM可能发生,因为内存太碎片而无法分配新对象。 MemoryStream将数据存储在缓冲区中。当它超过缓冲区限制时,它会分配一个容量增加一倍的新数据并复制旧数据。像这样复制250MB的数据将导致重新分配的批次,从而造成大量内存碎片。

可以通过在流的构造函数中指定所需的容量来避免这种情况。这将立即分配足够大的缓冲区。

尽管通过直接将其发送到浏览器来避免缓存此内容,情况会更好。

相关问题