2010-07-29 25 views
9

Tôi đang sử dụng Filestream để đọc tệp lớn (> 500 MB) và tôi nhận được OutOfMemoryException.OutOfMemoryException khi gửi tệp lớn 500MB bằng FileStream ASPNET

tôi sử dụng Asp.net, .net 3.5, Win2003, IIS 6.0

Tôi muốn điều này trong ứng dụng của tôi:

đọc dữ liệu từ Oracle

tập tin Giải nén sử dụng FileStream và BZip2

Đọc tập tin chưa nén và gửi đến trang asp.net để tải xuống.

Khi tôi đọc tệp từ đĩa, Không !!! và nhận OutOfMemory ...

. Mã của tôi là:

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; 
    } 

Bây giờ, tôi chỉ định vấn đề của mình tốt hơn.

Giải nén tệp bằng FileStream và BZip2 là OK, tất cả đều đúng.

Vấn đề là như sau:

đọc tập tin lớn chất béo trong đĩa (> 500 MB) trong byte [] và gửi byte để đáp ứng (asp.net) để tải về nó.

Khi dùng

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

public static byte[] ReadFully 

tôi nhận được báo lỗi: OutOfMemoryException ...

Nếu BufferedStream tốt hơn Stream (FileStream, MemoryStream, ...) ??

Sử dụng BufferedStream, Tôi có thể đọc tệp lớn 700 MB không ?? (bất kỳ mã nguồn mẫu nào sử dụng BufferedStream để tải xuống tệp lớn)

Tôi nghĩ, đây là câu hỏi: Không phải "cách đọc một tệp 500MB vào bộ nhớ?" , Nhưng "làm cách nào để gửi một tệp lớn tới luồng phản hồi ASPNET?"

tôi tìm thấy mã này bằng cách 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); 
    } 
} 

Có đang tốt ?? bất kỳ cải tiến nào cho hiệu suất cao ??

Một đồng nghiệp nói với tôi, sử dụng

Response.TransmitFile(filePath); 

Bây giờ, một câu hỏi khác, TransmitFile tốt hơn hoặc mã bởi Cheeso ??

Nhiều năm trước đây, trong MSDN tạp chí xuất hiện bài viết tuyệt vời về nó nhưng tôi không thể truy cập http://msdn.microsoft.com/msdnmag/issues/06/09/WebDownloads/,

Cập nhật: Bạn có thể truy cập bằng webarchive trong liên kết: https://web.archive.org/web/20070627063111/http://msdn.microsoft.com/msdnmag/issues/06/09/WebDownloads/

Bất kỳ lời đề nghị, ý kiến , mẫu mã nguồn ??

Trả lời

16

Tôi đã tạo trang tải xuống cho phép người dùng tải xuống tối đa 4gb (có thể nhiều hơn) vài tháng trước. Đây là đoạn mã hoạt động của tôi:

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(); 
     } 
    } 
2

Bạn không cần giữ toàn bộ tệp trong bộ nhớ vừa đọc và ghi vào luồng phản hồi trong vòng lặp.

Các vấn đề liên quan