【问题标题】:Convert HTML to PDF in MVC with iTextSharp in MVC Razor在 MVC Razor 中使用 iTextSharp 在 MVC 中将 HTML 转换为 PDF
【发布时间】:2013-05-07 04:46:20
【问题描述】:

我正在尝试在 MVC Razor 中使用 iTextSharp 将 HTML 转换为 PDF,但我尝试过的一切都没有奏效。有谁知道如何做到这一点?

【问题讨论】:

    标签: asp.net asp.net-mvc asp.net-mvc-4 itext html-to-pdf


    【解决方案1】:

    您可能会关注 CodeProject 上的详细信息和 step-by-step tutorial。它说明了如何使用 iTextSharp 将 ASP.NET MVC 视图作为 PDF 文件进行转换。请记住,尽管 iTextSharp 并非用于将 HTML 转换为 PDF,因此它可能无法很好地处理复杂的 HTML 页面和 CSS 样式。

    【讨论】:

    • 我想知道,如果 iTextSharp 不是用来将 HTML 转换为 PDF 的,那哪一个有免费源?
    • 如果今天日期 >14.07.2015 不要看这个答案!
    • @MDDDC 为什么不呢?那我应该去哪里看呢?
    • 本分步教程不是“剃刀”。是aspx、web表单……不是最新的。
    【解决方案2】:

    您应该查看RazorPDF,它使用 iText 生成 PDF,但方式更友好。

    【讨论】:

    • 嗨罗斯迪卡西姆。显然,最新的 iTextSharp 版本 (5.4.4) 无法与 RazorPDF 一起正常工作,并使其无用。
    • @real_yggdrasil 小心.. 最新的 iTextSharp(从 5.x 开始)有不同的许可证。 '渲染无用'也没有帮助..尝试通过一些示例或详细描述提交您的问题..
    • 我不同意。它已经变得毫无用处,因为它什么都不做,并且自 2012 年以来就没有更新过。
    【解决方案3】:

    如果你想编写普通的 xml,你可以在这里找到一种不同的方法,我发现它更简单、更轻便。

    http://www.codeproject.com/Articles/260470/PDF-reporting-using-ASP-NET-MVC3

    【讨论】:

      【解决方案4】:

      以下是使用 Razor 引擎NOT 和奇怪的<itext.. 标记实现此解决方案的方法。

      这样您就可以使用标准 html 输出完全控制 pdf 演示文稿。

      带有示例解决方案和源代码的项目可在此处获得 nuget 安装说明:

      https://github.com/andyhutch77/MvcRazorToPdf

      Install-Package MvcRazorToPdf
      

      这也使用了新的 itextsharp 许可证,因此不会受到其他答案中提到的任何负面影响。

      【讨论】:

      • 伙计,你太棒了,谢谢。我可以以某种方式更改页面方向吗?
      • @EdgarSalazar 没问题。由于它在下面使用 iTextXmlWorker,我认为您应该能够通过将 div 设置为您的横向比例来解决此问题。
      • @sports 是的,这里的表格示例:github.com/andyhutch77/MvcRazorToPdf/blob/master/…
      • 此 dll 不支持文化特定字符
      【解决方案5】:
      public virtual void printpdf(string html)    
      {
           String htmlText = html.ToString();
           Document document = new Document();
           string filePath = HostingEnvironment.MapPath("~/Content/Pdf/");
           PdfWriter.GetInstance(document, new FileStream(filePath + "\\pdf-"+Filename+".pdf", FileMode.Create));
      
           document.Open();    
           iTextSharp.text.html.simpleparser.HTMLWorker hw = new iTextSharp.text.html.simpleparser.HTMLWorker(document);       
           hw.Parse(new StringReader(htmlText));    
           document.Close();    
      }
      

      只需将html string 传递给参数 你将通过renderpartialview text = viewname....得到的那个字符串

      【讨论】:

        【解决方案6】:

        这是使用MVC的方法:

        [Route("ABCDD")]
        [HttpGet]
        public void ABCDD() {
            WebClient wc = new WebClient();
            // string url = HttpContext.Current.Request.Url.AbsoluteUri;
            string url = "http://localhost:3042/Reports/COAListing";
            string fileContent = wc.DownloadString(url);
        
            List<string> tableContents = GetContents(fileContent, table_pattern);
        
            string HTMLString = String.Join(" ", tableContents.ToArray());
        
            Document pdfDoc = new Document(PageSize.A4, 10f, 10f, 10f, 0f);
            PdfWriter.GetInstance(pdfDoc, HttpContext.Current.Response.OutputStream);
            pdfDoc.Open();
            pdfDoc.Add(new Paragraph("Welcome to dotnetfox"));
            List<IElement> htmlarraylist = HTMLWorker.ParseToList(new StringReader(HTMLString), null);
            for (int k = 0; k < htmlarraylist.Count; k++) {
                pdfDoc.Add((IElement) htmlarraylist[k]);
            }
        
            pdfDoc.Close();
            HttpContext.Current.Response.ContentType = "pdf/application";
            HttpContext.Current.Response.AddHeader("content-disposition", "attachment;" +
                    "filename=sample.pdf");
            HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
            HttpContext.Current.Response.Write(pdfDoc);
            HttpContext.Current.Response.End();
        }
        

        【讨论】:

        • 您的答案使用HTMLWorker,已弃用。你应该使用XMLWorker
        • 它给出错误 XMLWorker does not exist in current Context
        • 您使用的是哪个版本的 iTextSharp?你能在 iTextSharp 5.5.9 中重现它吗?
        • 是的,它的 iTextSharp 5.5.9
        • 你能在 iText 7.1.2 + pdfHTML 中重现它吗?
        【解决方案7】:

        使用Rotativa 是从 MVC HTML 视图转换为 PDF 的好方法(即使它不是直接关于 iTextSharp 的主题):

        Install-Package Rotativa
        

        这是基于wkhtmltopdf,但它比 iTextSharp 具有更好的 css 支持,并且与 MVC 集成非常简单,因为您可以简单地将视图返回为 pdf:

        public ActionResult GetPdf()
        {
            //...
            return new ViewAsPdf(model);// and you are done!
        }
        

        【讨论】:

        • 我与 Rotativa 合作过,它基于弹出窗口工作,需要解锁弹出窗口阻止程序。此外,使用 ViewAsPdf 或 ActionAsPdf 后,所有 Sessions 都将被清除。
        【解决方案8】:

        以下是 C# 中 MVC Razor 的完整示例,使用 evo html to pdf for .net 将当前 MVC 视图转换为 PDF 并将生成的 PDF 发送到浏览器以供下载:

        [HttpPost]
        public ActionResult ConvertCurrentPageToPdf(FormCollection collection)
        {
            object model = null;
            ViewDataDictionary viewData = new ViewDataDictionary(model);
        
            // The string writer where to render the HTML code of the view
            StringWriter stringWriter = new StringWriter();
        
            // Render the Index view in a HTML string
            ViewEngineResult viewResult = ViewEngines.Engines.FindView(ControllerContext, "Index", null);
            ViewContext viewContext = new ViewContext(
                    ControllerContext,
                    viewResult.View,
                    viewData,
                    new TempDataDictionary(),
                    stringWriter
                    );
            viewResult.View.Render(viewContext, stringWriter);
        
            // Get the view HTML string
            string htmlToConvert = stringWriter.ToString();
        
            // Get the base URL
            String currentPageUrl = this.ControllerContext.HttpContext.Request.Url.AbsoluteUri;
            String baseUrl = currentPageUrl.Substring(0, currentPageUrl.Length - "Convert_Current_Page/ConvertCurrentPageToPdf".Length);
        
            // Create a HTML to PDF converter object with default settings
            HtmlToPdfConverter htmlToPdfConverter = new HtmlToPdfConverter();
        
            // Convert the HTML string to a PDF document in a memory buffer
            byte[] outPdfBuffer = htmlToPdfConverter.ConvertHtml(htmlToConvert, baseUrl);
        
            // Send the PDF file to browser
            FileResult fileResult = new FileContentResult(outPdfBuffer, "application/pdf");
            fileResult.FileDownloadName = "Convert_Current_Page.pdf";
        
            return fileResult;
        }
        

        【讨论】:

          【解决方案9】:

          如果您使用的是 ASP.NET Core 并且 iTextSharp 对您来说不是那么重要,这里是我使用 PhantomJS 的解决方案:http://nikolay.it/Blog/2018/03/Generate-PDF-file-from-Razor-view-using-ASP-NET-Core-and-PhantomJS/37

          从 Razor 视图中获取 HTML 字符串

          这一步非常简单。在 ASP.NET Core 中有一个名为 IRazorViewEngine 的服务可以被注入然后用于获取视图。在为视图提供默认的ViewDataDictionaryActionContext 之后,我们可以请求将视图呈现为StringWriter,这可以很容易地转换为字符串。这是从给定 Razor 视图文件中获取字符串的现成代码:

          public interface IViewRenderService
          {
              Task<string> RenderToStringAsync(string viewName, object model);
          }
          
          public class ViewRenderService : IViewRenderService
          {
              private readonly IRazorViewEngine razorViewEngine;
              private readonly ITempDataProvider tempDataProvider;
              private readonly IServiceProvider serviceProvider;
          
              public ViewRenderService(
                  IRazorViewEngine razorViewEngine,
                  ITempDataProvider tempDataProvider,
                  IServiceProvider serviceProvider)
              {
                  this.razorViewEngine = razorViewEngine;
                  this.tempDataProvider = tempDataProvider;
                  this.serviceProvider = serviceProvider;
              }
          
              public async Task<string> RenderToStringAsync(string viewName, object model)
              {
                  var httpContext = new DefaultHttpContext { RequestServices = this.serviceProvider };
                  var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
          
                  using (var sw = new StringWriter())
                  {
                      var viewResult = this.razorViewEngine.GetView(null, viewName, false);
          
                      if (viewResult.View == null)
                      {
                          throw new ArgumentNullException($"{viewName} does not match any available view");
                      }
          
                      var viewDictionary =
                          new ViewDataDictionary(
                              new EmptyModelMetadataProvider(),
                              new ModelStateDictionary()) { Model = model };
          
                      var viewContext = new ViewContext(
                          actionContext,
                          viewResult.View,
                          viewDictionary,
                          new TempDataDictionary(actionContext.HttpContext, this.tempDataProvider),
                          sw,
                          new HtmlHelperOptions());
          
                      await viewResult.View.RenderAsync(viewContext);
                      return sw.ToString();
                  }
              }
          }
          

          这里有一个重要的想法:如果您使用视图编译(将视图预编译为YourProject.Web.PrecompiledViews.dll),那么使用GetView 方法而不是FindView 获取视图很重要。更多信息here

          使用 PhantomJS 从 HTML 生成 PDF 文件

          对于这个任务,我们将使用一个无头浏览器来呈现 HTML(其中包含所有 CSS 和 JS)。有很多这样的工具,但我将使用PhantomJS(可使用 JavaScript API 编写脚本的无头 WebKit)。 PhantomJS 可以非常快地将渲染的页面保存为小型 PDF。为了使 PDF 导出工作,我们需要一个 .js 文件,该文件将使用 PhantomJS API 告诉工具我们要导出文件:

          "use strict";
          var page = require('webpage').create(),
              system = require('system'),
              address,
              output;
          
          console.log('Usage: rasterize.js [URL] [filename] [paperformat]');
          address = system.args[1];
          output = system.args[2];
          page.viewportSize = { width: 600, height: 600 };
          page.paperSize = { format: system.args[3], orientation: 'portrait', margin: '0.5cm' };
          
          page.open(address, function (status) {
              if (status !== 'success') {
                  console.log('Unable to load the address!');
                  phantom.exit(1);
              } else {
                  window.setTimeout(function () {
                      page.render(output);
                      phantom.exit();
                  }, 200);
              }
          });
          

          接下来是运行phantomjs.exe 进程并传递rasterize.js 文件以及HTML 文件的路径和PDF 结果的输出文件名。这是在HtmlToPdfConverter.cs

          public interface IHtmlToPdfConverter
          {
              byte[] Convert(string htmlCode);
          }
          
          public class HtmlToPdfConverter : IHtmlToPdfConverter
          {
              public byte[] Convert(string htmlCode)
              {
                  var inputFileName = "input.html";
                  var outputFileName = "output.pdf";
                  File.WriteAllText(inputFileName, htmlCode);
                  var startInfo = new ProcessStartInfo("phantomjs.exe")
                                      {
                                          WorkingDirectory = Environment.CurrentDirectory,
                                          Arguments = string.Format(
                                              "rasterize.js \"{0}\" {1} \"A4\"",
                                              inputFileName,
                                              outputFileName),
                                          UseShellExecute = true,
                                      };
          
                  var process = new Process { StartInfo = startInfo };
                  process.Start();
          
                  process.WaitForExit();
          
                  var bytes = File.ReadAllBytes(outputFileName);
          
                  File.Delete(inputFileName);
                  File.Delete(outputFileName);
          
                  return bytes;
              }
          }
          

          如果您要在 Azure 中部署应用程序,请将 UseShellExecute 设置为 true 非常重要。

          一起使用代码

          既然我们现在已经实现了IViewRenderServiceIHtmlToPdfConverter,我们可以通过首先在您的ConfigureServices 方法所在的Startup.cs 文件中注册它们来开始使用它们(services.AddScoped&lt;IViewRenderService, ViewRenderService&gt;()services.AddScoped&lt;IHtmlToPdfConverter, HtmlToPdfConverter&gt;())。现在让我们看一下打包在一起的代码:

          private readonly IViewRenderService viewRenderService;
          private readonly IHtmlToPdfConverter htmlToPdfConverter;
          
          public DashboardController(
              IViewRenderService viewRenderService,
              IHtmlToPdfConverter htmlToPdfConverter)
          {
              this.viewRenderService = viewRenderService;
              this.htmlToPdfConverter = htmlToPdfConverter;
          }
          
          [HttpGet]
          public async Task<IActionResult> GetPdf(SomeInputModel input)
          {
              var model = this.GetViewModel(input);
              var htmlData = await this.viewRenderService.RenderToStringAsync("~/Views/Dashboard/GetPdf.cshtml", model);
              var fileContents = this.htmlToPdfConverter.Convert(htmlData);
              return this.File(fileContents, "application/pdf");
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-03-07
            • 2014-12-05
            • 1970-01-01
            • 1970-01-01
            • 2014-09-29
            相关资源
            最近更新 更多