如何在没有任何第三方工具的情况下将我的html Razor视图转换为pdf文档

时间:2014-05-11 07:45:20

标签: asp.net-mvc

我是MVC 4中的新手。我有一个html Razor视图,其中包含所有与表相关的数据。

我只是想在没有第三方工具的情况下将该视图转换为pdf文档。

3 个答案:

答案 0 :(得分:0)

MVC4 - 即使它是您的Frameworks的名称应该被理解为模型 - 模型 - 视图 - 控制器(MVC)。这种模式的想法是将这三个组件分开,以便在需要时用不同的渠道替换它们。

在您的情况下,Razor Template是一种用HTML生成VIEW的工具。 Razor仅限于HTML - 您的模式不是。通过MVC的设计,您可以使用任何其他工具将VIEW从HTML替换为PDF,XML或任何您想要的。

您应该寻找的是一种使用现有MODEL(非VIEW)并使用任何所需库生成PDF输出的方法。

答案 1 :(得分:0)

如果您使用的是ASP.NET Core,我的解决方案是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(无头WebKit脚本与JavaScript API)。 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<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");
}

答案 2 :(得分:0)

由于ASP.NET MVC没有内置的PDF功能,因此在没有第三方工具的情况下将Razor视图转换为PDF的唯一方法是自己编写转换代码。这将是一项艰巨的任务,几乎肯定不值得努力。我将从purchasing the ISO 32000-1 reference document开始,学习有关PDF格式如何工作的一切。在回答这个问题时,费用约为200瑞士法郎。