Asp.Net MVC So erhalten Sie eine Ansicht zum Generieren von PDF


73

Ich möchte eine Aktion auf einem Controller aufrufen. Lassen Sie den Controller die Daten aus dem Modell abrufen. Die Ansicht wird dann ausgeführt und generiert ein PDF. Das einzige Beispiel, das ich gefunden habe, ist ein Artikel von Lou http://whereslou.com/2009/04/12/returning-pdfs-from-an-aspnet-mvc-action . Sein Code ist sehr elegant. Die Ansicht verwendet ITextSharp, um das PDF zu generieren. Der einzige Nachteil ist, dass sein Beispiel die Spark View Engine verwendet. Gibt es eine Möglichkeit, mit der Standard-Microsoft-View-Engine etwas Ähnliches zu tun?


8
Die Verwendung der Spark View Engine ist ein Nachteil? Ich bin verwundet. :)
Loudej

Ich habe damit gekämpft. Spark mit iText war einfach zu verwenden, aber die PDF-Formatierung war begrenzt. Ich würde gerne Ihr Beispiel sehen, in dem Sie eine PDF-Vorlagendatei verwenden, Inhalte ändern und dann in einen Stream schreiben.
user275308

Überprüfen Sie dies heraus, RazorPDF: nyveldt.com/blog/post/Introducing-RazorPDF
Rosdi Kasim

Eine ausführliche Beschreibung der Vorgehensweise in ASP.NET MVC mit PhantomJS finden Sie hier: zizhujy.com/blog/post/2014/07/29/… . Ein Online-Beispiel für die Schritte des Blogposts finden Sie hier: zizhujy.com/en-US/PDFConverter . Dies funktioniert hervorragend, solange die Seite einen anonymen Besuch zulässt.
Jeff Tian

Für die Nachwelt verwenden wir jetzt Rotativa, das wkhtmltopdf
Eric Brown - Cal

Antworten:


83

Ich verwende iTextSharp, um dynamische PDFs in MVC zu generieren. Sie müssen lediglich Ihre PDF-Datei in ein Stream-Objekt einfügen und Ihr ActionResult gibt dann ein FileStreamResult zurück. Ich habe auch die Inhaltsdisposition festgelegt, damit der Benutzer sie herunterladen kann.

public FileStreamResult PDFGenerator ()
{
    Stream fileStream = GeneratePDF ();

    HttpContext.Response.AddHeader ("Inhaltsdisposition", 
    "Anhang; Dateiname = form.pdf");

    neues FileStreamResult zurückgeben (fileStream, "application / pdf");
}}

Ich habe auch Code, mit dem ich eine PDF-Vorlage erstellen, Text und Bilder darauf schreiben usw. (wenn Sie das möchten).

  • Hinweis: Sie müssen die Stream-Position auf 0 setzen.
privater Stream GeneratePDF ()
{
    // Erstelle dein PDF und füge es in den Stream ein ... pdf Variable unten
    // stammt aus einer Klasse, mit der ich Inhalte in PDF-Dateien schreibe

    MemoryStream ms = neuer MemoryStream ();

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

    return ms;
}}

5
Ich würde gerne ein Beispiel dafür sehen, wie diese "PDF-Klasse" im Beispiel aussieht, oder einige Hinweise zur Implementierung erhalten?
Jesperlind

1
Das einzige, was ich hinzufügen möchte, ist, dass diese Aktion nicht von einem partiellen Postback (Ajax) aufgerufen werden kann, sondern einen Html.ActionLink oder ähnliches verwendet.
Zonkflut

2
Code Projektartikel mit Beispielcode: codeproject.com/Articles/66948/…
Jakub Konecki

3
Das Hinzufügen des Content-Disposition-Headers funktioniert in FireFox aufgrund dieses Problems mit doppelter Content-Disposition nicht . Die richtige Lösung besteht darin, die FileDownloadName-Eigenschaft des FireStreamResult-Objekts festzulegen.
Alpav

@ David, in meinem Projekt habe ich eine rollenbasierte Autorisierung für Aktionen, aber wenn ich PDF verwende, wird nur der Anmeldebildschirm gedruckt
SAR

25

Unsere endgültige Antwort auf dieses Problem war die Verwendung von Rotativa .

Es schließt die WKhtmltopdf.exe wie einige der anderen Lösungen ab, ist aber bei weitem die am einfachsten zu verwendende, die ich gefunden habe

Ich habe alle anderen Antworten gewählt, die das Problem ebenfalls gut lösen, aber genau das haben wir verwendet, um das in der obigen Frage gestellte Problem zu lösen. Es unterscheidet sich von den anderen Antworten.

Hier ist ein Rotativa-Tutorial .

Nachdem Sie es installiert haben, ist dies alles, was Sie brauchen

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

Sehr sehr einfach.


3
Warum die Ablehnung, ich bin verwirrt. So lösen wir das Problem jetzt, daher habe ich die Frage aktualisiert, um sie auf dem neuesten Stand zu halten. Ich verstehe nicht. Wie kann ich es besser machen, wenn ich nicht verstehe, warum ich die Abwahl erhalten habe?
Eric Brown - Cal

3
Wieder eine Abwertung ohne Kommentar ... dies ist die Antwort, mit der wir das Problem gelöst haben. Ich habe mich besonders bemüht, zurück zu kommen und die Frage mit der aktuelleren Antwort zu aktualisieren. Ich bin verwirrt, wie das eine Abwertung bewertet, es sei denn, Sie mögen Rotativa einfach nicht.
Eric Brown - Cal

Brown Schöne Antwort ohne Code, das brauchen wir im 21. Jahrhundert. +1 für Kommentare und Antworten. Vielen Dank
Lerner

Es funktioniert einfach nicht. Wenn ich ViewAsPdf verwende, erhalte ich eine Fehlermeldung: "Der Verzeichnisname ist ungültig"
Robert Benyi

Stellen Sie sich in diesem Codeblock die Frage, was implizit einen Verzeichnisnamen enthält. Der Dateiname ... Stellen Sie also sicher, dass Sie sich auf dem richtigen Weg befinden, wo sich die PDF-Datei befindet.
Eric Brown - Cal

6

Das Erstellen eines Layouts in HTML und das anschließende Drucken in PDF ist der schnellste Weg.

Die Konvertierung von HTML in PDF wird von phantomjs , wkhtmltopdf oder jsreport bereitgestellt

jsreport bietet eine direkte Integration in asp.net mvc-Ansichten, in denen Sie die Controller-Aktion einfach mit einem Attribut markieren können und für Sie PDF anstelle von HTML drucken.

Mehr zu diesem Blogbeitrag

Haftungsausschluss: Ich bin der Autor von jsreport


1
Wenn Sie MVC verwenden, ist Rotativa ein wirklich netter Wrapper für wkhtmltopdf ... super einfach zu bedienen, wir haben ihn konvertiert, um dieses Problem jetzt zu lösen ... Es gab ein Problem mit Bildern, aber es gibt eine Problemumgehung für SO
Eric Brown - Cal

Ja, Rorativa ist eine schöne Hülle. jsreport ist eher ein Berichtsserver, der Bilder verarbeitet oder den Berichtsverlauf für Sie aufbewahrt.
Jan Blaha

6

Dies ist eine alte Frage, die aber immer noch relevant ist, und ich dachte, ich würde nur mitteilen, was ich implementiert habe, was gut funktioniert.

  1. Installieren Sie das NuGet-Paket TuesdayPechkin - eine Abzweigung in der Pechkin-Bibliothek, die auf WkHtmlToPdf basiert und eine Webkit-Engine zum Konvertieren von HTML-Seiten in PDF verwendet.

  2. Schreiben Sie einen kleinen Helfer, um eine Ansicht zu lesen und in eine HTML-Zeichenfolge zu konvertieren (mvcContext ist this.HttpContext). Das Ersetzen ist natürlich optional!:

    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() { }
    }
    

Die harte Arbeit der oben genannten war von hier: http://wouterdekort.blogspot.co.uk/2012/10/rendering-aspnet-mvc-view-to-string-in.html?showComment=1414603363455#c7863520150405064571

  1. Erstellen Sie eine MVC-Aktion, um das Dokument zu generieren

    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");
    }
    

Für diejenigen, die diesem Tutorial folgen und Fehler IPechkinund FactoryDinge haben, liegt es daran, dass es bereits veraltet ist. Bitte lesen Sie unter github.com/tuespetre/TuesPechkin, wie Sie das Repo selbst installieren und implementieren .
Chaintng

TuesPechkinVergessen Sie auch nicht, nach dem Herunterladen von Nuget herunterzuladen TuesPechkin.Wkhtmltox.Win32oder TuesPechkin.Wkhtmltox.Win64da es beim Herunterladen nicht enthalten ist.
Chaintng

Dies sollte eine der Top-Antworten sein. War genau das, wonach ich gesucht habe und es ist Open Source.
Alao


2

Ich habe gerade wkhtmltopdf verwendet, um das Layout in HTML zu erstellen, und danach konvertiere ich es in PDF.

Einfach, anpassbar, verdammt großartig :)


2
Ich nehme an, Sie meinen wkhtmltopdf
raider33

0

Sehr späte Antwort, aber ich stellte fest, dass die folgende URL mir half, meine Ergebnisse schnell zu erhalten:

(Stellen Sie sicher, dass Sie auf die iTextSharp-DLL verweisen, indem Sie die Nuget-Pakete verwenden.)

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

BEARBEITEN Dies ist der Code, mit dem ich die Tabelle etwas anders aussehen ließ (Dies ist auch Querformat:

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");
            }
        }

Hoffe das hilft auch jemand anderem.


0

Ein kleines Beispiel mit dem Rotativa-Paket in asp.net mvc

Wir werden eine Funktion zum Auffüllen der Daten erstellen. Wir werden Daten für 7 Tage (1. Februar 2018 - 7. Februar 2018) einfügen, die den ersten und den letzten Schlag für einen bestimmten Tag mit Anmerkungen zeigen.

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
            };
        }

Wir werden dann eine Funktion zum Herunterladen von PDF erstellen. Um das PDF herunterzuladen, müssen wir 2 Funktionen erstellen. 1. PDF herunterladen 2. PDF anzeigen

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);
        }

Sie können die detaillierte Erklärung unter diesem Link anzeigen. Besuchen Sie hier .

Curtesoy: thelearninguy.com

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.