[使用FileStream ASPNET发送500MB大文件时出现OutOfMemoryException

问题描述 投票:10回答:4

我正在使用Filestream读取大文件(> 500 MB),并且收到OutOfMemoryException。

我使用Asp.net,.net 3.5,win2003,iis 6.0

我想要在我的应用程序中使用这个:]

从Oracle读取数据

使用FileStream和BZip2解压缩文件

读取未压缩的文件,并将其发送到asp.net页面进行下载。

当我从磁盘读取文件时,失败!!!并获取OutOfMemory ...

。我的代码是:

using (var fs3 = new FileStream(filePath2, FileMode.Open, FileAccess.Read)) 
        { 
          byte[] b2 = ReadFully(fs3, 1024); 
        } 

 // http://www.yoda.arachsys.com/csharp/readbinary.html
 public static byte[] ReadFully(Stream stream, int initialLength) 
  { 
    // If we've been passed an unhelpful initial length, just 
    // use 32K. 
    if (initialLength < 1) 
    { 
      initialLength = 32768; 
    } 

    byte[] buffer = new byte[initialLength]; 
    int read = 0; 

    int chunk; 
    while ((chunk = stream.Read(buffer, read, buffer.Length - read)) > 0) 
    { 
      read += chunk; 

      // If we've reached the end of our buffer, check to see if there's 
      // any more information 
      if (read == buffer.Length) 
      { 
        int nextByte = stream.ReadByte(); 

        // End of stream? If so, we're done 
        if (nextByte == -1) 
        { 
          return buffer; 
        } 

        // Nope. Resize the buffer, put in the byte we've just 
        // read, and continue 
        byte[] newBuffer = new byte[buffer.Length * 2]; 
        Array.Copy(buffer, newBuffer, buffer.Length); 
        newBuffer[read] = (byte)nextByte; 
        buffer = newBuffer; 
        read++; 
      } 
    } 
    // Buffer is now too big. Shrink it. 
    byte[] ret = new byte[read]; 
    Array.Copy(buffer, ret, read); 
    return ret; 
  } 

现在,我更好地说明我的问题。

使用FileStream和BZip2解压缩文件就可以了,没事。

问题如下:

以字节[]读取磁盘中的大文件(> 500 MB),然后将字节发送到Response(asp.net)进行下载。

使用时

http://www.yoda.arachsys.com/csharp/readbinary.html

public static byte[] ReadFully

我收到错误:OutOfMemoryException ...

如果BufferedStream比Stream(FileStream,MemoryStream,...)更好?

使用BufferedStream,我可以读取700 MB的大文件吗? (使用BufferedStream下载大文件的任何示例代码源)

我认为,这是一个问题:不是“如何将500mb文件读入内存?” ,但是“如何将大文件发送到ASPNET Response流?”

我由Cheeso找到此代码:

using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))  
{  
   Response.BufferOutput= false;   // to prevent buffering 
   byte[] buffer = new byte[1024]; 
   int bytesRead = 0; 
   while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0)  
   { 
       Response.OutputStream.Write(buffer, 0, bytesRead); 
   } 
}

是好的代码吗?对高性能的任何改进?

一个同事说我,使用

Response.TransmitFile(filePath);

现在,另一个问题,更好的TransmitFile或Cheeso的代码??

很多年前,在《 msdn》杂志上刊登了有关它的好文章,但我无法访问http://msdn.microsoft.com/msdnmag/issues/06/09/WebDownloads/

更新

:您可以使用链接https://web.archive.org/web/20070627063111/http://msdn.microsoft.com/msdnmag/issues/06/09/WebDownloads/]中的webarchive进行访问。

任何建议,评论,示例代码源?

我正在使用Filestream读取大文件(> 500 MB),并且收到OutOfMemoryException。我使用Asp.net,.net 3.5,win2003,iis 6.0在我的应用程序中需要这样做:使用...

<<<我已经创建了下载页面,该页面允许用户在几个月前下载高达4GB(可能更多)的文件。这是我的工作片段:
private void TransmitFile(string fullPath, string outFileName) { System.IO.Stream iStream = null; // Buffer to read 10K bytes in chunk: byte[] buffer = new Byte[10000]; // Length of the file: int length; // Total bytes to read: long dataToRead; // Identify the file to download including its path. string filepath = fullPath; // Identify the file name. string filename = System.IO.Path.GetFileName(filepath); try { // Open the file. iStream = new System.IO.FileStream(filepath, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read); // Total bytes to read: dataToRead = iStream.Length; Response.Clear(); Response.ContentType = "application/octet-stream"; Response.AddHeader("Content-Disposition", "attachment; filename=" + outFileName); Response.AddHeader("Content-Length", iStream.Length.ToString()); // Read the bytes. while (dataToRead > 0) { // Verify that the client is connected. if (Response.IsClientConnected) { // Read the data in buffer. length = iStream.Read(buffer, 0, 10000); // Write the data to the current output stream. Response.OutputStream.Write(buffer, 0, length); // Flush the data to the output. Response.Flush(); buffer = new Byte[10000]; dataToRead = dataToRead - length; } else { //prevent infinite loop if user disconnects dataToRead = -1; } } } catch (Exception ex) { throw new ApplicationException(ex.Message); } finally { if (iStream != null) { //Close the file. iStream.Close(); } Response.Close(); } }

您不需要将整个文件保存在内存中,只需读取它并循环写入响应流。
asp.net stream download filestream out-of-memory
4个回答
2
投票

0
投票
1-使用RecyclableMemoryStream代替MemoryStream解决方案

0
投票
/// <summary>Based upon https://stackoverflow.com/a/3363015/595473 </summary> public class BufferedFileStreamResult : System.Web.Mvc.FileStreamResult { public BufferedFileStreamResult(System.IO.Stream stream, string contentType, string fileDownloadName) : base(stream, contentType) { FileDownloadName = fileDownloadName; } public int BufferSize { get; set; } = 16 * 1024 * 1024;//--16MiB protected override void WriteFile(System.Web.HttpResponseBase response) { try { response.Clear(); response.AddHeader("Content-Disposition", $"attachment; filename={FileDownloadName}"); response.AddHeader("Content-Length", FileStream.Length.ToString()); byte[] buffer; int bytesRead; while (response.IsClientConnected)//--Prevent infinite loop if user disconnects { buffer = new byte[BufferSize]; //--Read the data in buffer if ((bytesRead = FileStream.Read(buffer, 0, BufferSize)) == 0) { break;//--Stop writing if there's nothing left to write } //--Write the data to the current output stream response.OutputStream.Write(buffer, 0, bytesRead); //--Flush the data to the output response.Flush(); } } finally { FileStream?.Close(); response.Close(); } } }
© www.soinside.com 2019 - 2024. All rights reserved.