2011-05-20 72 views
1

我想從MVC3網頁生成pdf。我已經看過所有通常的教程,但通常情況下,一個人很匆忙,並不知道自己在做什麼,所以我正在爲它做一個早餐。使用ITextSharp和mvc損壞的pdf

當我單擊視圖上的動作鏈接以生成PDF文件時,似乎創建了該文件,但是當我嘗試打開它時,我從Adobe Reader那裏得到了非常有用的消息「...文件已損壞,無法修復「。

我在哪裏出了錯?

public FileStreamResult PDFGenerator() 
    { 
     Stream fileStream = GeneratePDF(); 

     HttpContext.Response.AddHeader("content-disposition", "attachment; filename=form.pdf"); 

     return new FileStreamResult(fileStream, "application/pdf"); 
    } 

    private Stream GeneratePDF() 
    { 
     MemoryStream ms = new MemoryStream(); 

     Document doc = new Document(); 
     PdfWriter writer = PdfWriter.GetInstance(doc, ms); 
     doc.Open(); 
     doc.Add(new Paragraph("Hello")); 

     ms.Position = 0; 
     ms.Flush(); 

     writer.Flush(); 

     return ms; 
    } 

回答

3

您必須關閉文檔。嘗試像這樣:

public ActionResult PDFGenerator() 
{ 
    var doc = new Document(); 
    using (var stream = new MemoryStream()) 
    { 
     var writer = PdfWriter.GetInstance(doc, stream); 
     doc.Open(); 
     doc.Add(new Paragraph("Hello")); 
     doc.Close(); 
     return File(stream.ToArray(), "application/pdf", "test.pdf"); 
    } 
} 

但這很醜。我會建議你更多的MVCish方法,包括編寫一個自定義的ActionResult。作爲這樣的一個額外好處是,你的控制器動作將更加容易單元測試中隔離:

public class PdfResult : FileResult 
{ 
    public PdfResult(): base("application/pdf") 
    { } 

    public PdfResult(string contentType): base(contentType) 
    { } 

    protected override void WriteFile(HttpResponseBase response) 
    { 
     var cd = new ContentDisposition 
     { 
      Inline = false, 
      FileName = "test.pdf" 
     }; 
     response.AppendHeader("Content-Disposition", cd.ToString()); 

     var doc = new Document(); 
     var writer = PdfWriter.GetInstance(doc, response.OutputStream); 
     doc.Open(); 
     doc.Add(new Paragraph("Hello")); 
     doc.Close(); 
    } 
} 

,然後在你的控制器動作:

public ActionResult PDFGenerator() 
{ 
    return new PdfResult(); 
} 

當然這是可以採取的一個步驟更進一步,有這個PdfResult採取視圖模型的構造函數的參數,並基於這個視圖模型的某些屬性的PDF:

public ActionResult PDFGenerator() 
{ 
    MyViewModel model = ... 
    return new PdfResult(model); 
} 

現在的事我們開始看起來不錯。

+0

doh!做的伎倆......感謝您的快速反應! – seanicus 2011-05-20 15:42:55

+0

感謝您的獎勵代碼,以及! – seanicus 2011-05-20 15:48:24

+0

跟進問題...從代碼組織的角度來看,自定義操作結果類的最佳位置在哪裏?在控制器文件夾中? – seanicus 2011-05-20 16:25:03