web-dev-qa-db-ja.com

PDF形式でASP.NET MVCビューをレンダリングする方法

私はこの質問のためにExpertPDFのHTMLからPDFへの変換ユーティリティを使用しています(十分なドキュメントがある場合は他のライブラリを利用できます)。

要するに、特定の方法でフォーマットされたビューがあり、それをPDFユーザーがディスクに保存できるドキュメントとしてレンダリングしたいのですが。

これまでのところ、PrintService(IPrintServiceインターフェイスを実装)であり、この実装にはPrintToPDF()の2つのオーバーロードがあります。1つはURLのみを受け取り、もう1つはHTML文字列を受け取り、どちらもbyte []を返します。私は、HTML文字列を必要とする2番目のオーバーロードの詳細のみを調べました。

私のコントローラーからしたいことは次のようなものです:

public FileStreamResult Print(int id)
{
    var model = _CustomRepository.Get(id);
    string renderedView = SomethingThatRendersMyViewAsAString(model);
    Stream byteStream = _PrintService.PrintToPdf(renderedView);
    HttpContext.Response.AddHeader("content-disposition", 
        "attachment; filename=report.pdf");
    return new FileStreamResult(byteStream, "application/pdf");  
}

理論的にはPDF=ページにレンダリングされます。これは私が助けを求めている「SomethingThatRendersMyViewAsAString」です。ビューの文字列表現を取得する簡単な方法はありますか?またはおそらく私は単にURLのオーバーロードに固執し、ビューにURLを渡す必要があります...他の考えはありますか?

ありがとう!

24
nkirkes

OnResultExecuting中にResponseを利用して、Filterプロパティを結果のHTMLをMemoryStreamに格納するものに置き換えることができる場合があります。次に、OnResultExecuted中にResponseをクリアして、それをPDF変換の結果に置き換えます。ただし、URLからHTMLを取得するよりもこれが優れているかどうかはわかりません。

 public FileStreamResult Print(int id)
 {
     var model = _CustomRepository.Get(id);
     this.ConvertToPDF = true;
     return View( "HtmlView" );
 }

 public override OnResultExecuting( ResultExecutingContext context )
 {
      if (this.ConvertToPDF)
      {
          this.PDFStream = new MemoryStream();
          context.HttpContext.Response.Filter = new PDFStreamFilter( this.PDFStream );
      }
 }

 public override OnResultExecuted( ResultExecutedContext context )
 {
      if (this.ConvertToPDF)
      {
          context.HttpContext.Response.Clear();
          this.PDFStream.Seek( 0, SeekOrigin.Begin );
          Stream byteStream = _PrintService.PrintToPDF( this.PDFStream );
          StreamReader reader = new StreamReader( byteStream );
          context.HttpContext.Response.AddHeader( "content-disposition",
                 "attachment; filename=report.pdf" );
          context.HttpContext.Response.AddHeader( "content-type",
                 "application/pdf" );
          context.HttpContext.Response.Write( reader.ReadToEnd() );
      }
}

PDFStreamFilterは、「書き込み」メソッドをオーバーライドし、代わりにデータをメモリストリームに送信する必要があります。

10
tvanfosson

私のソリューションはNugetパッケージであるRotativa http://nuget.org/packages/Rotativa にパッケージ化しました。 wkhtmltopdfに基づいています。

使い方は本当に簡単です。

HTMLページではなく、Pdfとして機能させたいアクションがある。タイプActionAsPdfのActionResultを返すアクションを定義できます(RouteAsPdfも使用できます)。したがって、コードは次のとおりです。

public ActionResult PrintIndex()
{
    return new ActionAsPdf("Index", new { name = "Giorgio" }) { FileName = "Test.pdf" };
}

Name = "Giorgio"はルートパラメータです。

印刷するアクションがWebフォーム認証([Authorize]属性)で保護されている場合でも機能します

98
Giorgio Bozio

これは、ビューをメールテンプレートとして使用したいのと同じような問題のようです。ビューの文字列表現を取得するために私が見つけた最良の答えはここにありました: ビューを文字列としてレンダリングする

1
Jason

私が見つけた最良のパッケージはRazorPDFで、 iTextSharp に基づいてNuGet.orgでパッケージとして入手できます。 Azure Webサイトで動作します:

https://nuget.org/packages/RazorPDF