2016-03-23 28 views
6

Stack trace trông giống nhưTại sao tôi nhận được "Không thể truy cập Luồng đã đóng" ở đây?

[ObjectDisposedException: Không thể truy cập một Stream khép kín.]
System.IO .__ Error.StreamIsClosed() 53
System.IO.MemoryStream.Read (Byte [] buffer, Int32 offset, Int32 count) +11411219 System.Web.Mvc.FileStreamResult.WriteFile (Phản hồi HttpResponseBase) +81 System.Web.Mvc.FileResult.ExecuteResult (ControllerContext context) +168
System.Web.Mvc.ControllerActionInvoker. InvokeActionResult (ControllerContext controllerContext, ActionResult actionResult) +13

sau gọi

 //Byte[] bytes; 
     using (var ms = new MemoryStream()) 
     { 
      using (var doc = new Document()) 
      { 
       using (var writer = PdfWriter.GetInstance(doc, ms)) 
       { 

        doc.Open(); 
        //var example_html = @"<p>This <em>is </em><span class=""headline"" style=""text-decoration: underline;"">some</span> <strong>sample <em> text</em></strong><span style=""color: red;"">!!!</span></p>"; 
        var example_html = System.IO.File.ReadAllText(Path.Combine(Server.MapPath("~/EmailTemplates"), "template.html")); 
        var example_css = @".headline{font-size:200%}"; 
        using (var srHtml = new StringReader(example_html)) 
        { 
         iTextSharp.tool.xml.XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, srHtml); 
        } 
        using (var msCss = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(example_css))) 
        { 
         using (var msHtml = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(example_html))) 
         { 
          iTextSharp.tool.xml.XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, msHtml, msCss); 
         } 
        } 


        doc.Close(); 
       } 
      } 
      //bytes = ms.ToArray(); 
      return File(ms, "application/pdf", "Test.pdf"); 
     } 

Tôi đã đọc MemoryStream - Cannot access a closed Stream, nhưng đó không phải là kịch bản giống nhau vì tôi không sử dụng StreamReader

Edit: Vẫn không làm việc với

[OutputCache(NoStore = true, Duration = 0)] 
    public ActionResult Run() 
    { 
     Byte[] bytes; 
     var ms = new MemoryStream(); 
     try 
     { 
      using (var doc = new Document()) 
      { 
       using (var writer = PdfWriter.GetInstance(doc, ms)) 
       { 
        writer.CloseStream = false; 
        doc.Open(); 
        var example_html = @"<p>This <em>is </em><span class=""headline"" style=""text-decoration: underline;"">some</span> <strong>sample <em> text</em></strong><span style=""color: red;"">!!!</span></p>"; 
        //var example_html = System.IO.File.ReadAllText(Path.Combine(Server.MapPath("~/EmailTemplates"), "LinkEmailTemplate.html")); 
        var example_css = @".headline{font-size:200%}"; 
        using (var msCss = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(example_css))) 
        { 
         using (var msHtml = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(example_html))) 
         { 
          iTextSharp.tool.xml.XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, msHtml, msCss); 
         } 
        } 
        doc.Close(); 
       } 
      } 
      bytes = ms.ToArray(); 
      ms.Position = 0; 
      return File(ms, "application/pdf", "Test.pdf"); 
     } 
     catch 
     { 
      ms.Dispose(); 
      throw; 
     }   
    } 
+1

Vì luồng đã bị đóng ngay sau khi bạn thoát khỏi phương thức hành động. Khi khung nhìn cố gắng truy cập nó, nó thấy nó đã bị đóng. –

+1

'Vẫn không hoạt động với' - xác định 'không hoạt động'. Ngoài ra bạn có một biến có tên là 'byte' mà không làm bất cứ điều gì nhưng tôi tò mò nếu có bất cứ điều gì trong mảng này trước khi phương pháp của bạn thoát. – Igor

+2

* Tại sao * bạn sao chép nội dung luồng vào một mảng byte? Nếu bạn làm điều đó không có lý do gì để trả về dòng * với 'File (..)', chỉ trả về mảng byte, ví dụ 'File (bytes ...)' –

Trả lời

0

Lớp PdfWriter có thể đóng bạn r stream. Đảm bảo đặt thuộc tính CloseStream thành sai.

Tiếp theo, bạn nên không sử dụng using trên MemoryStream đây, kể từ khi kết quả FileStreamResult hành động sẽ chăm sóc xử lý dòng sau khi gửi nó đi. Hiện tại, luồng thực sự đã bị đóng (bằng cách vứt bỏ) trước khi quá trình gửi diễn ra.

Ngoài ra, bạn nên tìm luồng trở lại vị trí 0 trước khi gửi tệp.

Bạn có thể bọc toàn bộ phần trong một try...catch tuy nhiên để xử lý luồng trong trường hợp xảy ra lỗi (nhưng GC cuối cùng sẽ xử lý nó và MemoryStream nếu sully quản lý, do đó không bắt buộc).

+0

'Document' là' iTextSharp.Text.Document' –

6

Luồng đã bị đóng ngay khi bạn thoát khỏi phương thức hành động, hoặc đúng hơn là khối using (var ms = new MemoryStream()) {.

Bạn không cần phải vứt bỏ MemoryStream. Đối tượng FileStreamResult được trả về bởi File(ms, "application/pdf", "Test.pdf"); sẽ dispose it after rendering. Các mã mà thực sự sẽ gửi dữ liệu dòng là:

protected async override Task WriteFileAsync(HttpResponse response) 
{ 
    var outputStream = response.Body; 

    using (FileStream) 
    { 
     var bufferingFeature = response.HttpContext.Features.Get<IHttpBufferingFeature>(); 
     bufferingFeature?.DisableResponseBuffering(); 

     await FileStream.CopyToAsync(outputStream, BufferSize); 
    } 
} 

Bạn có thể thay thế bằng khối này với:

var ms = new MemoryStream(); 
try 
{ 
    //.. 
    //From Igor's comment. FileStreamResult won't reset the stream position itself 
    ms.Position=0; 
    return File(ms, "application/pdf", "Test.pdf"); 
} 
catch 
{ 
    ms.Dispose(); 
    throw; 
} 

để đảm bảo rằng con suối bị xử lý nếu xảy ra lỗi.

CẬP NHẬT

Như Igor đã đề cập, và là mã nguồn chương trình, FileStreamResult sẽ không reset vị trí dòng. Bạn sẽ phải đặt thành 0 trước khi gọi return File(...)

+1

Bạn cũng có thể muốn đặt lại vị trí trong luồng bộ nhớ trước khi chuyển nó vào Tệp. 'ms.Position = 0;' – Igor

+0

Cảm ơn, đã cập nhật –

+0

Có điều gì khác mà tôi có thể bị thiếu không? Tôi sẽ dán mã cập nhật của mình lên trên –

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