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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1324597/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 15:09:49  来源:igfitidea点击:

How to render an ASP.NET MVC View in PDF format

c#.netasp.net-mvcpdfpdf-generation

提问by nkirkes

I'm working with ExpertPDF's Html-to-PDF conversion utility for this question (although I'm open to other libraries if there's sufficient documentation).

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

In short, I have a view that is formatted a specific way and I would like to render it as a PDF document the user can save to disk.

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

What I have so far is a PrintService (which implements an IPrintService interface) and this implementation has two overloads for PrintToPDF(), one that takes just a URL and another that takes an HTML string, and both of which return a byte[]. I've only worked out the details of the second overload which requires the HTML string.

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

What I would like to do from my controller is something like:

我想从我的控制器做的是:

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");  
}

which in theory would render a PDF to the page. It's the "SomethingThatRendersMyViewAsAString" that I'm looking for help with. Is there a quick way to get the string representation of a View? Or perhaps I should just stick with the URL overload and pass in a URL to the view... Any other thoughts?

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

Thanks!

谢谢!

采纳答案by tvanfosson

You might be able to tap into the Response during OnResultExecuting and replace the Filter property with something that stores the resultant HTML in a MemoryStream. Then you could clear the Response during OnResultExecuted and replace it with the results of your PDF conversion. I'm not sure that this would be better than just getting the HTML from the URL, though.

您可以在 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() );
      }
}

The PDFStreamFilter would need to override the "Write" method(s) and send the data to the memory stream instead.

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

回答by Jason

This sounds like a similar problem I had where I wanted to use Views as email templates. The best answer I found for getting the string representation of a View was here: Render a view as a string

这听起来像是我想将视图用作电子邮件模板时遇到的类似问题。我找到的获取视图字符串表示的最佳答案在这里:将视图渲染为字符串

回答by Giorgio Bozio

I packaged my solution in a Nuget package: Rotativa http://nuget.org/packages/Rotativa. It's based on wkhtmltopdf.

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

Usage is really simple.

用法真的很简单。

Having an action you would like to serve as Pdf, instead of Html page. You can define an action that returns an ActionResult of the type ActionAsPdf (RouteAsPdf is also available). So the code is just:

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

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

With name = "Giorgio" being a route parameter.

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

It works even if the action to print is protected by web forms authentication ([Authorize] attribute)

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

回答by Leonel Sanches da Silva

The best package I've found is the RazorPDF, available as a package at NuGet.org, based on iTextSharp. Works on Azure Web Sites:

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

https://nuget.org/packages/RazorPDF

https://nuget.org/packages/RazorPDF