使用ASP.NET 5导出为pdf

时间:2016-05-02 13:11:05

标签: asp.net-core asp.net-core-mvc dnx50

我正在研究MVC 6应用程序(DNX Core 5.0框架)。不幸的是,我找不到任何pdf导出库。

任何帮助将不胜感激。

5 个答案:

答案 0 :(得分:12)

我终于找到了一种从.NET Core(没有任何.NET框架依赖项)生成pdf的方法是在我的.NET Core应用程序中使用Node.js。 以下示例说明如何在干净的ASP.NET核心Web应用程序项目(Web API模板)中实现HTML到PDF转换器。

安装NuGet包Microsoft.AspNetCore.NodeServices

在Startup.cs中添加像这样的行services.AddNodeServices()

public void ConfigureServices(IServiceCollection services)
{
    // ... all your existing configuration is here ...

    // Enable Node Services
    services.AddNodeServices();
}

现在安装所需的Node.js包:

从命令行将工作目录更改为.NET Core项目的根目录并运行这些命令。

npm init

并按照说明创建package.json文件

npm install jsreport-core --save
npm install jsreport-jsrender --save
npm install jsreport-phantom-pdf --save

在包含

的项目根目录中创建文件pdf.js
module.exports = function (callback) {
    var jsreport = require('jsreport-core')();

    jsreport.init().then(function () {
        return jsreport.render({
            template: {
                content: '<h1>Hello {{:foo}}</h1>',
                engine: 'jsrender',
                recipe: 'phantom-pdf'
            },
            data: {
                foo: "world"
            }
        }).then(function (resp) {
            callback(/* error */ null, resp.content.toJSON().data);
        });
    }).catch(function (e) {
        callback(/* error */ e, null);
    })
};

有关jsreport-core的更多说明,请查看here

现在在调用此Node.js脚本的Mvc控制器中创建一个操作

[HttpGet]
public async Task<IActionResult> MyAction([FromServices] INodeServices nodeServices)
{
    var result = await nodeServices.InvokeAsync<byte[]>("./pdf");

    HttpContext.Response.ContentType = "application/pdf";

    string filename = @"report.pdf";
    HttpContext.Response.Headers.Add("x-filename", filename);
    HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "x-filename");
    HttpContext.Response.Body.Write(result, 0, result.Length);
    return new ContentResult();
}

当然,您可以使用nodeServices返回的byte[]执行任何操作,在此示例中,我只是从控制器操作中输出它,以便可以在浏览器中查看。

您还可以使用resp.content.toString('base64')pdf.js的base64编码字符串在Node.js和.NET Core之间交换数据并使用 在操作中var result = await nodeServices.InvokeAsync<byte[]>("./pdf");然后解码base64编码的字符串。

<小时/> 的替代

大多数pdf生成器解决方案仍然依赖于.NET 4.5 / 4.6框架。 上面的两个答案(JsReport和RazorPDFCore)都不适用于.NET Core。

如果您不想使用Node.js,似乎有一些付费替代方案:

  • NReco.PdfGenerator.LT
  • EVO HTML to PDF Converter Client for .NET Core
  • 用于.NET Core的Winnovative HTML to PDF Converter Client

我还没有尝试过这些。

我希望我们很快会在这方面看到一些开源进展。

答案 1 :(得分:10)

如果您必须依赖Core,您将有两个选择:

1 - 稍等一下

Core仍然是RC1,慢慢转向RC2,你很快就找不到很多lib。由于.NET Core受到了很多关注,所以第一个库应该在几个月后推出,但我猜你不得不等待RC2的发布。

2 - Fork(或类似)

您可以获取最符合您需求的开源项目,fork(如果在GitHub上)或者只是下载并开始更新到.NET Core。我只是用DapperExtensions做到了这一点,它就像一个魅力。你甚至可以为你添加一些辣;)

另一方面,如果你只是需要一些有效但不需要嵌入.NET Core的东西,我设法让JsReport正常工作。它将启动它自己的基于Node的服务器(嵌入式服务器),但集成非常简单(使用AspNet Core非常自己的Dependecy Injection系统!)并创建PDF而没有进一步的问题。

如果你感兴趣,这里有一些指示:

1 - 参考文献

将它们添加到project.json:

"jsreport.Embedded": "0.8.1",
"jsreport.Client": "0.8.1"

2 - AspNet集成

之后,按照jsReport here的说明操作。您可以在此处配置AspNet DI系统:

public void ConfigureServices(IServiceCollection services)
{
   // ...
   var _server = new EmbeddedReportingServer();
   _server.StartAsync().Wait();
   services.AddInstance<IEmbeddedReportingServer>(_server);
   services.AddSingleton<IReportingService>((s) => { return s.GetRequiredService<IEmbeddedReportingServer>().ReportingService; });
   // ...
}

要使用您,您只需要接收IReportingService或手动从控制器上的Resolver抓取它。

3 - 用法

public IActionResult SomeReport()
{
   // This is <my> type of usage. It's a bit manual because I'm currently loading reports from DB. You can use it in a diferent way (check jsReport docs).
   var service = Resolver.GetRequiredService<jsreport.Client.IReportingService>();

   var phantomOptions = new jsreport.Client.Entities.Phantom()
   {
      format = "A4",
      orientation = "portrait",
      margin = "0cm"
   };
   phantomOptions.footer = "<h2>Some footer</h2>";
   phantomOptions.footerHeight = "50px";
   phantomOptions.header = "<h2>Some header</h2>";
   phantomOptions.headerHeight = "50px";
   var request = new jsreport.Client.RenderRequest()
   {
      template = new jsreport.Client.Entities.Template()
      {
         content = "<div>Some content for your report</div>",
         recipe = "phantom-pdf",
         name = "Your report name",
         phantom = phantomOptions
      }
   };

   var _report = service.RenderAsync(request).Result;

   // Request file download.
   return File(_report.Content, "application/pdf", "Some fancy name.pdf");
}

4 - 重要提示:您的服务器无法启动(缺少zip文件)

由于NuGet对AspNet项目的更改,您必须手动移动一些不会自动移动的内容文件。

首先,找到嵌入式服务器的dnx缓存。应该是这样的:
C:\Users\<name>\.dnx\packages\jsreport.Embedded\0.8.1

您会注意到一个名为content的文件夹。只需将其内容(两个文件:node.exejsreport-net-embedded.zip)复制到lib\net45

因此,简单明了,万无一失:从中复制内容(仅限文件) C:\Users\<name>\.dnx\packages\jsreport.Embedded\0.8.1\contents
进入 C:\Users\<name>\.dnx\packages\jsreport.Embedded\0.8.1\lib\net45

这应该解决启动问题。请记住:首次启动将提取文件,并且应该花几分钟时间。在那之后,它会快得多。

答案 2 :(得分:2)

Necromancing。

向NodeJS添加依赖关系是理想的恕我直言,特别是考虑到.NET Core自包含部署。

根据2017年,您可以使用my port of PdfSharpCore to .NET Core 1.1
解析字体,它可以使用图像。附带一个很好的示例应用程序。但是,您必须更换数据库部件。

积分转到:
https://github.com/groege/PdfSharpCore

有点过时,并且不包含如何将其与图像一起使用的示例。

请注意,在使用相应功能之前,您需要注册font-resolver和imageSource-Implementation:

PdfSharpCore.Fonts.GlobalFontSettings.FontResolver = new FontResolver();

MigraDocCore.DocumentObjectModel.MigraDoc.DocumentObjectModel
    .Shapes.ImageSource.ImageSourceImpl = 
          new PdfSharpCore.ImageSharp.ImageSharpImageSource();

答案 3 :(得分:2)

我知道这个问题是在不久前提出来的,我知道已经有几个答案已经提供,可能适合某些项目。但是我最近创建了一个GitHub存储库,允许直接从C#代码创建PDF,而不需要nodejs,javascript或razor。此功能集目前有点受限,但它会生成带有图像的PDF(仅在此阶段为.jpg),形状和格式化文本。该库与.net core 2.0一起使用,不依赖于任何其他PDF生成工具。

请注意,这是我自己的存储库:https://github.com/GZidar/CorePDF

我计划随着时间的推移添加功能,但至少目前这可能为其他人提供了在自己的项目中包含简单PDF功能而无需额外工具的基础。

答案 4 :(得分:1)

我修改了RazorAnt/RazorPDF,它只适用于较旧的MVC版本,可以与ASP.NET Core一起使用。 RazorPDFCore ,可在nugetgithub上找到:

使用示例

class YourBaseController : RazorPDF.Controller {
    // [...]
    public IActionResult Pdf() {
        var model = /* any model you wish */
        return ViewPdf(model);
    }
}

在您的Startup.cs

services.AddMVc();

之前添加以下行
services.AddSingleton<PdfResultExecutor>();

请注意:

在使用RazorPDF.Controller方法

之前,您需要从基本控制器获取ViewPdf()