如何以PDF格式呈现ASP.NET MVC视图

nki*_*kes 24 .net c# pdf asp.net-mvc pdf-generation

我正在使用ExpertPDF的Html-to-PDF转换实用程序来解决这个问题(尽管如果有足够的文档,我会对其他库开放).

简而言之,我有一个以特定方式格式化的视图,我想将其呈现为用户可以保存到磁盘的PDF文档.

我到目前为止是一个PrintService(它实现了一个IPrintService接口),这个实现有两个PrintToPDF()重载,一个只接受一个URL,另一个接受一个HTML字符串,两者都返回一个byte [].我只计算了需要HTML字符串的第二个重载的细节.

我想从我的控制器做的事情是这样的:

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");  
}
Run Code Online (Sandbox Code Playgroud)

这在理论上会将PDF呈现给页面.这是我正在寻求帮助的"SomethingThatRendersMyViewAsAString".有没有快速的方法来获取视图的字符串表示?或许我应该坚持使用URL重载并将URL传递给视图......还有其他想法吗?

谢谢!

Gio*_*zio 96

我将我的解决方案打包在Nuget包中:Rotativa http://nuget.org/packages/Rotativa.它基于wkhtmltopdf.

用法非常简单.

有一个动作,你想作为Pdf,而不是Html页面.您可以定义一个返回ActionAsPdf类型的ActionResult的操作(RouteAsPdf也可用).所以代码只是:

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

名称="Giorgio"是路线参数.

即使要通过Web窗体身份验证([Authorize]属性)保护要打印的操作,它也能工作

  • 这是迄今为止我遇到的最简单的asp.net mvc解决方案,非常感谢... (5认同)
  • 在Azure Web角色中有效,但由于信任级别的限制,无法在Azure网站上运行. (3认同)
  • 太棒了 - 谢谢!我会注意到我必须指定表单身份验证cookie名称(否则将呈现登录页面)并将呈现器更改为使用打印介质样式(FormsAuthenticationCookieName ="MyCookie",CustomSwitches =" - print-media-type" ).很容易! (2认同)
  • @GuruprasadRao,它是通过pdf登录页面生成的 (2认同)

tva*_*son 10

您可以在OnResultExecuting期间使用Response并将Filter属性替换为在MemoryStream中存储结果HTML的内容.然后,您可以在OnResultExecuted期间清除响应,并将其替换为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() );
      }
}
Run Code Online (Sandbox Code Playgroud)

PDFStreamFilter需要覆盖"Write"方法并将数据发送到内存流.