Asp.Net MVC如何获取视图以生成PDF


73

我想在控制器上调用一个动作。让控制器从模型中获取数据。然后运行该视图并生成PDF。我发现的唯一示例是在Lou的一篇文章中http://whereslou.com/2009/04/12/returning-pdfs-from-an-aspnet-mvc-action。他的代码非常优雅。该视图正在使用ITextSharp生成PDF。唯一的缺点是他的示例使用了Spark View Engine。有没有办法使用标准的Microsoft视图引擎来做类似的事情?


8
使用Spark视图引擎是一个缺点吗?我受伤了 :)
Loudej,2009年

我为此感到挣扎。带iText的Spark易于使用,但PDF格式受到限制。我很想看看您的样本,您在其中使用模板PDF文件,更改内容然后写入流。
user275308'2


有关在PhantomJS中使用ASP.NET MVC进行操作的详细说明,请登录:zizhujy.com/blog/post/2014/07/29/…。此处提供了一个应用博客帖子步骤的在线示例:zizhujy.com/en-US/PDFConverter。只要页面允许匿名访问,此方法就很好用。
Jeff Tian

为了后代的缘故,我们现在使用Rotativa,它包装了wkhtmltopdf
Eric Brown-Cal

Answers:


83

我使用iTextSharp在MVC中生成动态PDF。您需要做的就是将PDF放入Stream对象,然后ActionResult返回一个FileStreamResult。我还设置了内容配置,以便用户可以下载它。

公共FileStreamResult PDFGenerator()
{
    流fileStream = GeneratePDF();

    HttpContext.Response.AddHeader(“ content-disposition”, 
    “附件;文件名= form.pdf”);

    返回新的FileStreamResult(fileStream,“ application / pdf”);
}

我也有代码,使我能够提取模板PDF,向其中写入文本和图像等(如果您想这样做)。

  • 注意:您必须将“流”位置设置为0。
私人Stream GeneratePDF()
{
    //创建您的pdf并将其放入流中... pdf变量如下
    //来自我用来将内容写入PDF文件的类

    MemoryStream ms =新的MemoryStream();

    byte [] byteInfo = pdf.Output();
    ms.Write(byteInfo,0,byteInfo.Length);
    ms.Position = 0;

    返回ms;
}

5
我希望看到示例中的“ pdf类”是什么样的示例,或者获得有关如何实现它的一些提示?
jesperlind

1
我唯一要添加的是,不能从部分回发(ajax)调用此Action,而是使用Html.ActionLink等。
zonkflut 2010年

2
代码项目的文章示例代码:codeproject.com/Articles/66948/...
的Jakub Konecki

3
由于存在重复的Content-Disposition的问题,因此无法在FireFox中添加Content-Disposition标头。正确的解决方案是设置FireStreamResult对象的FileDownloadName属性。
alpav 2011年

@David,在我的项目中,我具有基于角色的操作授权,但是当我使用pdf时,它仅显示登录屏幕
SAR

25

我们对该问题的最终答案是使用Rotativa

它像其他解决方案一样包装了WKhtmltopdf.exe,但这是我发现的最简单的使用方法

我继续投票,其他所有也能很好解决问题的答案,但这就是我们用来解决上面问题中所提出问题的方式。它与其他答案不同。

这是Rotativa教程

安装后,这就是您所需要的

public ActionResult PrintInvoice(int invoiceId)
{
  return new ActionAsPdf(
                 "Invoice", 
                 new { invoiceId= invoiceId }) 
                 { FileName = "Invoice.pdf" };
}

非常非常简单。


3
为什么不赞成,我感到困惑。这就是我们现在解决问题的方式,因此我更新了问题以使问题保持​​最新。我不明白 如果我不明白为什么我会投反对票,我该如何做得更好?
埃里克·布朗-2014年

3
再次投反对票,不加评论...这是我们用来解决问题的答案。我付出了额外的努力,以最新的答案返回并更新问题。除非您只是不喜欢轮状烤肉,否则我很困惑那该如何进行否决投票。
埃里克·布朗-2014年

Brown完全没有任何代码的美丽答案,这是21世纪我们所需要的。+1表示评论和答案。谢谢。–
学习者

它根本不起作用。当我使用ViewAsPdf时,它给我一个错误:“目录名称无效”
Robert Benyi

问自己一个问题,在该代码块中,隐含的目录名称是什么?文件名...因此,请确保您要正确定位.pdf的位置。
埃里克·布朗

6

用html创建布局并随后打印为pdf是最快的方法。

html到pdf的转换是由phantomjswkhtmltopdfjsreport提供的

jsreport提供与asp.net mvc视图的直接集成,您可以在其中仅用属性标记控制器动作,它将为您打印pdf而不是html。

有关此博客文章的更多信息

免责声明:我是jsreport的作者


1
如果您使用的是MVC,则Rotativa是wkhtmltopdf的非常好的包装器...超级易于使用,我们已经转换为它可以解决此问题...图像有问题,但是有解决方法
埃里克·布朗-2014年

是的,Rorativa是一个不错的包装器。jsreport是一个报告服务器,可以处理图像或为您保留报告历史记录。
2014年

6

这是一个古老的问题,但仍然是一个相关的问题,我想我只想分享一下我已经实施的效果很好的问题。

  1. 安装NuGet包TuesPechkin-Pechkin库中的一个基于WkHtmlToPdf的派生,该派生使用Webkit引擎将HTML页面转换为PDF。

  2. 编写一个小助手来读取视图并将其转换为HTML字符串(mvcContext是this.HttpContext)。当然,替换是可选的!:

    public static string RenderViewToString(HttpContextBase mvcContext, string area, string controllerName, string viewName, object model)
    {
        var context = System.Web.HttpContext.Current;
        var contextBase = mvcContext;
        var routeData = new RouteData();
        if (area == null) area = "";
    
        routeData.DataTokens.Add("area", area);
    
        routeData.Values.Add("controller", controllerName);
    
        var controllerContext = new ControllerContext(contextBase,
                                                routeData,
                                                new EmptyController());
    
        var razorViewEngine = new RazorViewEngine();
        var razorViewResult = razorViewEngine.FindView(controllerContext,
                                                    viewName,
                                                    "",
                                                false);
    
        var writer = new StringWriter();
        var viewContext = new ViewContext(controllerContext,
                                    razorViewResult.View,
                                    new ViewDataDictionary(model),
                                    new TempDataDictionary(),
                                    writer);
        razorViewResult.View.Render(viewContext, writer);
    
        string hostAddress = context.Request.Url.Scheme + "://" + context.Request.Url.Authority;
    
        return writer.ToString()
                     .Replace("src=\"/", "src=\"" + hostAddress + "/")
                     .Replace("<link href=\"/", "<link href=\"" + hostAddress + "/");                         
    }
    
    class EmptyController : ControllerBase
    {
        protected override void ExecuteCore() { }
    }
    

上面的艰苦工作来自这里:http : //wouterdekort.blogspot.co.uk/2012/10/rendering-aspnet-mvc-view-to-string-in.html?showComment=1414603363455#c7863520150405064571

  1. 创建一个MVC操作以生成文档

    public ActionResult DownloadPDF(long CentreID)
    {
        var model = GetModel()
    
        IPechkin converter = Factory.Create();
        byte[] result = converter.Convert(Helpers.PDF.RenderViewToString(this.HttpContext, "area", "controller", "action", model);
        MemoryStream outputStream = new MemoryStream();
        outputStream.Write(result, 0, result.Length);
        outputStream.Position = 0;
    
        return File(outputStream, "application/pdf", "filename.pdf");
    }
    

对于那些遵循本教程并且有错误IPechkin和其他Factory问题的人,因为它已经过时了。请在github.com/tuespetre/TuesPechkin上阅读如何在仓库上安装和实现。
chaintng

而且,TuesPechkin从nuget下载后,请不要忘记下载,TuesPechkin.Wkhtmltox.Win32否则TuesPechkin.Wkhtmltox.Win64下载时将不包含该内容。
chaintng

这应该是最重要的答案之一。正是我一直在寻找的东西,它是开源的。
Alao 2015年



0

回复很晚,但是我发现以下URL可以帮助我快速获得结果:

(确保您通过使用Nuget包来引用iTextSharp DLL)

https://www.aspsnippets.com/Articles/Export-Grid-Html-Table-data-from-database-to-PDF-file-using-iTextSharp-in-ASPNet-MVC.aspx

编辑 这是我用来使表格看起来有些不同的代码(这也是横向的:

public string GetCssForPdf()
        {
            string css = "";

            css = "th, td" +
                   "{" +
                       "font-family:Arial; font-size:10px" +
                    "}";

            return css;
        }

[HttpPost]
        [ValidateInput(false)]
        public FileResult Export(string GridHtml)
        {
            string webgridstyle = GetCssForPdf();

            string exportData = String.Format("<html><body>{0}{1}</body></html>", "<style>" + webgridstyle + "</style>", GridHtml);
            var bytes = System.Text.Encoding.UTF8.GetBytes(exportData);

            using (var input = new MemoryStream(bytes))
            {
                var output = new MemoryStream();
                var document = new iTextSharp.text.Document(PageSize.A4, 50, 50, 50, 50);
                var writer = PdfWriter.GetInstance(document, output);

                document.SetPageSize(iTextSharp.text.PageSize.A4.Rotate());
                Font headerFont = FontFactory.GetFont("Verdana", 10);
                Font rowfont = FontFactory.GetFont("Verdana", 10);

                writer.CloseStream = false;
                document.Open();

                var xmlWorker = iTextSharp.tool.xml.XMLWorkerHelper.GetInstance();
                xmlWorker.ParseXHtml(writer, document, input, System.Text.Encoding.UTF8);
                document.Close();
                output.Position = 0;

                return File(output, "application/pdf", "Pipeline_Report.pdf");

                //return new FileStreamResult(output, "application/pdf");
            }
        }

希望这对其他人也有帮助。


0

一个在asp.net mvc中使用rotativa软件包的小例子

我们将创建一个函数来填充数据。我们将插入7天(2018年2月1日至2018年2月7日)的数据,其中显示特定日期的第一个拳和最后一个拳。

public ReportViewModel PopulateData()
        {
            var attendances = new List<Attendance>
            {
                new Attendance{ClassName = "present",Day = new DateTime(2018, 02, 01).ToString("ddd"),Date = new DateTime(2018, 02, 01).ToString("d"),FirstPunch = "09:01:00",LastPunch = "06:00:01",Remarks = ""},
                new Attendance{ClassName = "absent",Day = new DateTime(2018, 02, 02).ToString("ddd"),Date = new DateTime(2018, 02, 02).ToString("d"),FirstPunch = "",LastPunch = "",Remarks = "Absent"},
                new Attendance{ClassName = "holiday",Day = new DateTime(2018, 02, 03).ToString("ddd"),Date = new DateTime(2018, 02, 03).ToString("d"),FirstPunch = "",LastPunch = "",Remarks = "Democracy Day"},
                new Attendance{ClassName = "present",Day = new DateTime(2018, 02, 04).ToString("ddd"),Date = new DateTime(2018, 02, 04).ToString("d"),FirstPunch = "09:05:00",LastPunch = "06:30:01",Remarks = ""},
                new Attendance{ClassName = "present",Day = new DateTime(2018, 02, 05).ToString("ddd"),Date = new DateTime(2018, 02, 05).ToString("d"),FirstPunch = "09:01:00",LastPunch = "06:00:01",Remarks = ""},
                new Attendance{ClassName = "leave",Day = new DateTime(2018, 02, 06).ToString("ddd"),Date = new DateTime(2018, 02, 06).ToString("d"),FirstPunch = "",LastPunch = "",Remarks = "Sick Leave"},
                new Attendance{ClassName = "present",Day = new DateTime(2018, 02, 07).ToString("ddd"),Date = new DateTime(2018, 02, 07).ToString("d"),FirstPunch = "08:35:00",LastPunch = "06:15:01",Remarks = ""}
            };


            return new ReportViewModel
            {
                UserInformation = new UserInformation
                {
                    FullName = "Ritesh Man Chitrakar",
                    Department = "Information Science"
                },
                StartDate = new DateTime(2018, 02, 01),
                EndDate = new DateTime(2018, 02, 07),
                AttendanceData = attendances
            };
        }

然后,我们将为DownloadPdf创建一个函数。要下载pdf文件,我们需要创建2个函数。1.下载pdf 2.查看pdf

public ActionResult DownloadPdf()
        {
            var filename = "attendance.pdf";

            /*get the current login cookie*/
            var cookies = Request.Cookies.AllKeys.ToDictionary(k => k, k => Request.Cookies[k]?.Value);

            return new ActionAsPdf("PdfView", new
            {
                startDate = Convert.ToDateTime(Request["StartDate"]),
                endDate = Convert.ToDateTime(Request["EndDate"])
            })
            {
                FileName = filename,
                /*pass the retrieved cookie inside the cookie option*/
                RotativaOptions = {Cookies = cookies}
            };
        }

public ActionResult PdfView()
        {
            var reportAttendanceData = PopulateData();

            return View(reportAttendanceData);
        }

您可以在此链接上查看详细说明。拜访这里

Curtesoy:thelearninguy.com

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.