2012-06-21 36 views
17

Tôi đã có ấn tượng rằng khi bạn gọi Flush() trong đối tượng StreamWriter nó ghi vào luồng cơ bản, nhưng dường như điều này không đúng với mã của tôi.StreamWriter ghi vào MemoryStream

Thay vì ghi vào tệp của tôi, nó sẽ không viết gì cả. Bất kỳ ý tưởng mà tôi đang đi sai?

public FileResult DownloadEntries(int id) 
    { 
     Competition competition = dataService.GetCompetition(id); 
     IQueryable<CompetitionEntry> entries = dataService.GetAllCompetitionEntries().Where(e => e.CompetitionId == competition.CompetitionId); 

     MemoryStream stream = new MemoryStream(); 
     StreamWriter csvWriter = new StreamWriter(stream, Encoding.UTF8); 

     csvWriter.WriteLine("First name,Second name,E-mail address,Preferred contact number,UserId\r\n"); 

     foreach (CompetitionEntry entry in entries) 
     { 
      csvWriter.WriteLine(String.Format("{0},{1},{2},{3},{4}", 
       entry.User.FirstName, 
       entry.User.LastName, 
       entry.User.Email, 
       entry.User.PreferredContactNumber, 
       entry.User.Id)); 
     } 

     csvWriter.Flush(); 

     return File(stream, "text/plain", "CompetitionEntries.csv"); 
    } 
+2

Cân nhắc đặt MemoryStream và StreamWriter của bạn trong việc sử dụng báo cáo cho thu gom rác thải thích hợp. – neontapir

+0

@neontapir Tôi chưa làm tròn để dọn dẹp mã nhưng sẽ sau đó. Chúc mừng – ediblecode

+0

@neontapir, bình luận sai cho trường hợp cụ thể này: điều này sẽ chỉ làm cho vấn đề nghiêm trọng hơn/hiển nhiên ... –

Trả lời

24

Tôi tin rằng bạn cần đặt Stream.Position = 0. Khi bạn viết, nó tiến lên vị trí đến cuối luồng. Khi bạn vượt qua nó để File() nó bắt đầu từ vị trí của nó - ở cuối.

Tôi nghĩ rằng đây sẽ làm việc (không cố gắng để biên dịch này):

stream.Position = 0; 
return File(stream, "text/plain", "CompetitionEntries.csv"); 

Và cách này bạn không tạo ra bất kỳ đối tượng mới hoặc sao chép các mảng tiềm ẩn.

+2

Xin lưu ý rằng bạn * không được * xử lý văn bản và luồng trong mã của bộ điều khiển. Khi sao chép được dán, bạn có thể cần thêm nhận xét vào mã của mình về điều đó. –

7

MemoryStream của bạn được đặt ở cuối. Mã tốt hơn sẽ là tạo luồng bộ nhớ R/o mới trên cùng một bộ đệm bằng cách sử dụng hàm tạo MemoryStream(Byte[], Int32, Int32, Boolean).

đơn giản r/w trên đệm tỉa:

return File(new MemoryStream(stream.ToArray()); 

R/o mà không cần sao chép bộ đệm nội bộ:

return File(new MemoryStream(stream.GetBuffer(), 0, (int)stream.Length, false); 

Lưu ý: cẩn thận không để xử lý luồng mà bạn đang trở về thông qua File (Suối). Nếu không, bạn sẽ nhận được "ObjectDisposedException" của một số loại. I E. nếu bạn chỉ cần đặt vị trí của luồng gốc thành 0 và đưa StreamWriter vào sử dụng, bạn sẽ nhận được luồng trả về được xử lý.

+0

Được sắp xếp ngay. Cảm ơn bạn – ediblecode

+0

Tôi cũng đã thêm thận trọng khi sử dụng 'using' với chỉnh sửa của tôi. –

+0

Thú vị. Như tôi thấy dưới đây, tôi đã có thể nhận được một cái gì đó tương tự như làm việc với các tuyên bố sử dụng. – neontapir

2

Trong chơi với điều này, tôi có nguyên mẫu sau đây để làm việc:

using System.Web.Mvc; 
using NUnit.Framework; 

namespace StackOverflowSandbox 
{ 
[TestFixture] 
public class FileStreamResultTest 
{ 
    public FileStreamResult DownloadEntries(int id) 
    { 
     // fake data 
     var entries = new[] {new CompetitionEntry { User = new Competitor { FirstName = "Joe", LastName = "Smith", Email = "[email protected]", Id=id.ToString(), PreferredContactNumber = "555-1212"}}}; 

     using (var stream = new MemoryStream()) 
     { 
      using (var csvWriter = new StreamWriter(stream, Encoding.UTF8)) 
      { 
       csvWriter.WriteLine("First name,Second name,E-mail address,Preferred contact number,UserId\r\n"); 

       foreach (CompetitionEntry entry in entries) 
       { 
        csvWriter.WriteLine(String.Format("{0},{1},{2},{3},{4}", 
                 entry.User.FirstName, 
                 entry.User.LastName, 
                 entry.User.Email, 
                 entry.User.PreferredContactNumber, 
                 entry.User.Id)); 
       } 

       csvWriter.Flush(); 
      } 

      return new FileStreamResult(new MemoryStream(stream.ToArray()), "text/plain"); 
     } 
    } 

    [Test] 
    public void CanRenderTest() 
    { 
     var fileStreamResult = DownloadEntries(1); 
     string results; 
     using (var stream = new StreamReader(fileStreamResult.FileStream)) 
     { 
      results = stream.ReadToEnd(); 
     } 
     Assert.IsNotEmpty(results); 
    } 
} 

public class CompetitionEntry 
{ 
    public Competitor User { get; set; } 
} 

public class Competitor 
{ 
    public string FirstName; 
    public string LastName; 
    public string Email; 
    public string PreferredContactNumber; 
    public string Id; 
} 
} 
Các vấn đề liên quan