我是MVC 4中的新手。我有一个html Razor视图,其中包含所有与表相关的数据。
我只是想在没有第三方工具的情况下将该视图转换为pdf文档。
答案 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
这一步非常简单。 ASP.NET Core中有一个名为IRazorViewEngine
的服务,可以注入然后用于获取视图。在为视图提供默认ViewDataDictionary
和ActionContext
之后,我们可以请求将视图呈现为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。
对于此任务,我们将使用无头浏览器来呈现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
非常重要。
由于我们现在已经实现了IViewRenderService
和IHtmlToPdfConverter
,我们可以首先将它们注册到您的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瑞士法郎。