【问题标题】:How to render an ASP.NET MVC View in PDF format如何以 PDF 格式呈现 ASP.NET MVC 视图
【发布时间】:2010-11-22 09:57:33
【问题描述】:

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

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

到目前为止,我有一个 PrintService(它实现了一个 IPrintService 接口),这个实现有两个 PrintToPDF() 的重载,一个只接受一个 URL,另一个接受一个 HTML 字符串,两者都返回一个字节[]。我只计算了需要 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");  
}

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

谢谢!

【问题讨论】:

  • mannish - 你有没有在任何地方发布你的解决方案?这将非常有用。蒂亚

标签: c# .net asp.net-mvc pdf pdf-generation


【解决方案1】:

我将我的解决方案打包在 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" };
}

name = "Giorgio" 作为路由参数。

即使要打印的操作受到 Web 表单身份验证([Authorize] 属性)的保护,它也可以工作

【讨论】:

  • 这是迄今为止我遇到的最简单的 asp.net mvc 解决方案,非常感谢...
  • 这太棒了 - 谢谢!我会注意到我必须指定表单身份验证 cookie 名称(否则将呈现登录页面)并将渲染器更改为使用打印媒体样式(FormsAuthenticationCookieName = "MyCookie", CustomSwitches = "--print-media-type" )。很简单!
  • Rotativa 似乎在 MVC4 上失败了。当我返回 ActionAsPdf 时,我看到屏幕上显示的是字符串而不是 PDF。
  • 适用于 Azure Web 角色,但由于信任级别的限制,不适用于 Azure 网站。
  • @GuruprasadRao ,结果是 pdf 上的登录页面
【解决方案2】:

您可能能够在 OnResultExecuting 期间访问 Response 并将 Filter 属性替换为将结果 HTML 存储在 MemoryStream 中的内容。然后您可以在 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() );
      }
}

PDFStreamFilter 需要覆盖“Write”方法并将数据发送到内存流。

【讨论】:

  • 我找到了一个减少代码的解决方案,但您提供的答案是一个潜在的解决方案。拦截 Result 执行的好主意...我会尽快发布我的解决方案。
【解决方案3】:

这听起来与我想将视图用作电子邮件模板的类似问题。我发现获取视图的字符串表示的最佳答案是:Render a view as a string

【讨论】:

  • 我看到了那个帖子。根据对 brightmix 帖子的评论,我最终使用了类似的解决方案。我会尽快发布解决方案。
【解决方案4】:

我发现的最好的包是 RazorPDF,它可以在 NuGet.org 上作为一个包提供,基于 iTextSharp。适用于 Azure 网站:

https://nuget.org/packages/RazorPDF

【讨论】:

    猜你喜欢
    • 2019-12-03
    • 2023-03-18
    • 2011-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多