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?

Eric Brown - Cal
quelle
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;
}}
David
quelle
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.

Eric Brown - Cal
quelle
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

Jan Blaha
quelle
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");
    }
    
McGaz
quelle
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
5

Ich bin auch auf dieses http://www.codeproject.com/Articles/260470/PDF-reporting-using-ASP-NET-MVC3 gestoßen . Es ist einfach und schnell und passt gut zu MVC.

Der einzige Nachteil ist jedoch, dass es nicht ganz flexibel ist, ein anständiges Layout zu haben. Beispielsweise haben Sie nicht viel Kontrolle über Tabellen und Zellenränder über HTML. Es unterstützt sozusagen das Erzwingen neuer Seiten, aber Sie müssen einen Patch auf iTextsharp anwenden.

Sean Dong
quelle
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 :)

NicoJuicy
quelle
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.

AxleWack
quelle
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

Ritesh Chitrakar
quelle