Asp.net

使用 FileStream ASPNET 發送 500MB 大文件時出現 OutOfMemoryException

  • May 14, 2020

我正在使用 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)

$$ $$並將字節發送到響應(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 響應流?”

我通過 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/

更新:您可以在連結中使用webarchive訪問: https ://web.archive.org/web/20070627063111/http://msdn.microsoft.com/msdnmag/issues/06/09/WebDownloads/

任何建議,意見,範常式式碼源?

我已經創建了下載頁面,允許使用者在幾個月前下載多達 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();
       }
   }

引用自:https://stackoverflow.com/questions/3362849