2009-03-09 47 views
12

Tôi đang tạo một dịch vụ tải xuống đơn giản để người dùng có thể tải xuống tất cả hình ảnh của mình từ trang web bên ngoài. Để làm điều đó tôi chỉ cần nén mọi thứ vào luồng http.Truyền trực tuyến tệp zip qua http .net với SharpZipLib

Tuy nhiên có vẻ như mọi thứ được lưu trữ trong bộ nhớ và dữ liệu không được gửi tới tệp zip hoàn tất và đầu ra đã đóng. Tôi muốn dịch vụ bắt đầu gửi cùng một lúc và không sử dụng quá nhiều bộ nhớ.

public void ProcessRequest(HttpContext context) 
{ 
    List<string> fileNames = GetFileNames(); 
    context.Response.ContentType = "application/x-zip-compressed"; 
    context.Response.AppendHeader("content-disposition", "attachment; filename=files.zip"); 
    context.Response.ContentEncoding = Encoding.Default; 
    context.Response.Charset = ""; 

    byte[] buffer = new byte[1024 * 8]; 

    using (ICSharpCode.SharpZipLib.Zip.ZipOutputStream zipOutput = new ICSharpCode.SharpZipLib.Zip.ZipOutputStream(context.Response.OutputStream)) 
    { 
     foreach (string fileName in fileNames) 
     { 
      ICSharpCode.SharpZipLib.Zip.ZipEntry zipEntry = new ICSharpCode.SharpZipLib.Zip.ZipEntry(fileName); 
      zipOutput.PutNextEntry(zipEntry); 
      using (var fread = System.IO.File.OpenRead(fileName)) 
      { 
       ICSharpCode.SharpZipLib.Core.StreamUtils.Copy(fread, zipOutput, buffer); 
      } 
     } 
     zipOutput.Finish(); 
    } 

    context.Response.Flush(); 
    context.Response.End(); 
} 

Tôi có thể thấy bộ nhớ của bộ xử lý phát triển trong khi tạo tệp và sau đó giải phóng bộ nhớ khi gửi xong. Làm thế nào để tôi làm điều này mà không cần sử dụng quá nhiều bộ nhớ?

Trả lời

11

Disable response buffering với context.Response.BufferOutput = false; và xóa cuộc gọi Flush từ cuối mã của bạn.

+0

+1. Response.End là khắc nghiệt và không cần thiết cũng có. – AnthonyWJones

+0

Có nhiều cách khác để xử lý các tệp rất lớn, tôi tin rằng, cho phép các yêu cầu riêng biệt nhận được các phần riêng biệt của phản hồi. Tôi sẽ nén tệp vào đĩa để có thể phân phối nó trong nhiều yêu cầu mà không cần phải nén lại mỗi lần. –

0

sử dụng Response.BufferOutput = false; khi bắt đầu ProcessRequest và phản hồi tuôn ra sau mỗi tệp.

+1

Flush không làm bất cứ điều gì hữu ích khi tính năng đệm tắt. – AnthonyWJones

0

FYI. Đây là mã đang hoạt động để đệ quy thêm toàn bộ cây tệp, với phát trực tuyến tới trình duyệt:

string path = @"c:\files"; 

Response.Clear(); 
Response.ContentType = "application/zip"; 
Response.AddHeader("Content-Disposition", string.Format("attachment; filename=\"{0}\"", "hive.zip")); 
Response.BufferOutput = false; 

byte[] buffer = new byte[1024 * 1024]; 
using (ZipOutputStream zo = new ZipOutputStream(Response.OutputStream, 1024 * 1024)) { 
    zo.SetLevel(0); 
    DirectoryInfo di = new DirectoryInfo(path); 
    foreach (string file in Directory.GetFiles(di.FullName, "*.*", SearchOption.AllDirectories)) { 
     string folder = Path.GetDirectoryName(file); 
     if (folder.Length > di.FullName.Length) { 
      folder = folder.Substring(di.FullName.Length).Trim('\\') + @"\"; 
     } else { 
      folder = string.Empty; 
     } 
     zo.PutNextEntry(new ZipEntry(folder + Path.GetFileName(file))); 
     using (FileStream fs = File.OpenRead(file)) { 
      ICSharpCode.SharpZipLib.Core.StreamUtils.Copy(fs, zo, buffer); 
     } 
     zo.Flush(); 
     Response.Flush(); 
    } 
    zo.Finish(); 
} 

Response.Flush(); 
Các vấn đề liên quan