18

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

4

9 回答 9

34

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

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

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

https://github.com/andyhutch77/MvcRazorToPdf

Install-Package MvcRazorToPdf

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

于 2013-11-25T17:05:14.270 回答
4

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

于 2013-05-20T09:14:52.580 回答
4
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....

于 2014-01-29T06:58:33.210 回答
3

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

于 2013-05-13T07:56:24.900 回答
2

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

Install-Package Rotativa

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

public ActionResult GetPdf()
{
    //...
    return new ViewAsPdf(model);// and you are done!
}
于 2016-08-10T15:32:30.670 回答
2

这是 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;
}
于 2016-09-28T09:08:29.833 回答
0

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

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

于 2013-07-29T09:04:53.643 回答
0

这是如何使用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();
}
于 2016-05-18T17:13:01.527 回答
0

如果您使用的是 ASP.NET Core 而 iTextSharp 对您来说并不重要,这里是我使用 PhantomJS 的解决方案:http: //nikolay.it/Blog/2018/03/Generate-PDF-file-from-Razor-view-使用-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. 更多信息在这里

使用 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我们可以通过首先将它们注册到Startup.cs您的 ConfigureServices 方法所在的文件中来开始使用它们(services.AddScoped<IViewRenderService, ViewRenderService>()services.AddScoped<IHtmlToPdfConverter, HtmlToPdfConverter>())。现在让我们看看打包在一起的代码:

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");
}
于 2018-03-29T11:03:51.440 回答