10

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

任何帮助将不胜感激。

4

5 回答 5

14

我终于找到了一种从 .NET Core(没有任何 .NET 框架依赖项)生成 pdf 的方法,即在我的 .NET Core 应用程序中使用 Node.js。以下示例显示如何在干净的 ASP.NET Core 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.

现在在调用此 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')您还可以使用inpdf.js和 use in 操作在 Node.js 和 .NET Core 之间通过 base64 编码字符串交换数据var result = await nodeServices.InvokeAsync<byte[]>("./pdf");,然后解码 base64 编码字符串。


备择方案

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

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

  • NReco.PdfGenerator.LT
  • 适用于 .NET Core 的 EVO HTML 到 PDF 转换器客户端
  • Winnovative HTML to PDF Converter Client for .NET Core

我还没有尝试过这些。

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

于 2017-01-19T11:10:06.090 回答
10

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

1 - 稍等

核心仍然是 RC1,慢慢地转向 RC2,你不会很快找到太多的库。由于 .NET Core 受到了广泛关注,第一个库应该会在几个月后发布,但我猜你至少要等待 RC2 版本。

2 - 叉子(或类似的)

您可以获取最适合您需求的开源项目、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 的说明进行操作。您可以在此处配置 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 文件)

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

首先,找到嵌入式服务器的 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.

那应该可以解决启动问题。请记住:第一次启动将提取文件,应该需要几分钟。在那之后,它会快得多。

于 2016-05-03T20:54:11.050 回答
3

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

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

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

于 2017-09-15T08:59:17.290 回答
2

我已经修改了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()

于 2016-12-23T15:56:41.633 回答
2

死灵术。

恕我直言,添加对 NodeJS 的依赖是不理想的,尤其是考虑到 .NET Core 自包含部署。

根据 2017 年,您可以使用我的 PdfSharpCore 移植到 .NET Core 1.1
解析字体,并且它可以使用图像。附带一个不错的示例应用程序。但是,您必须更换 DB 部分。

学分转到:
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();
于 2017-04-18T13:10:29.017 回答