Häufig hören wir von VB.NET- oder C# Programmierern den Wunsch PDF Dokumente aus ASP.NET-Anwendungen erstellen zu können. Diese Anleitung zeigt ihnen, wie dies möglich ist.

Bei der Arbeit mit ASP.NET unter IIS ist es oft eine Herausforderung, mit dem Thema Sicherheit richtig umzugehen. Dies ist auch ein wichtiges Problem, wenn sie ein PDF drucken und an den Benutzer übertragen möchten. Hoffentlich hilft Ihnen das folgende dabei, diese Herausforderungen zu meistern und sie mit einer guten PDF Lösung für Ihre ASP.NET-Anwendung auf den richtigen Weg zu bringen.

Am Ende dieser Seite finden sie einen Link zum Quellcode, der zum Erstellen dieses Beispiels verwendet werden kann.

Was macht das Beispiel?

Das Beispiel ist ein ASP.NET-Handler, der ein PDF-Dokument erstellt und an den Website-Besucher überträgt. Der PDF-Code kann in einem normalen ASP.NET-Formular sowie in diesem Handler abgelegt werden.

Drucken sie aus ASP.NET mithilfe der PrintDocument-Klasse

Dieses Beispiel konzentriert sich auf das Drucken von C# mit der PrintDocument-Klasse und dem PrintPageEventHandler. Dies ist die typische Art, wie sie die Funktionalität des Druckens in ihre Microsoft.NET-Anwendung integrieren. Obwohl das Beispiel in C# geschrieben ist, sollten die Prinzipien auch für VB.NET oder andere .NET-kompatible Sprachen anwendbar sein.

Die Herausforderungen

Wenn wir von ASP.NET aus ein PDF drucken möchten, stehen wir vor einigen Herausforderungen. Der erste ist die Sicherheit um IIS und der zweite ist Parallelisierung.

Druck und Sicherheit

Bei einer normalen IIS-Installation ist der Benutzerkontext darauf beschränkt, Dateien bereitzustellen und Skripts auszuführen. Dieses Beispiel wurde für die Ausführung mit Standardsicherheitseinstellungen erstellt. Das bedeutet, dass sie die vorhandenen Berechtigungen für den IIS-Benutzer nicht erweitern müssen, damit dies funktioniert. Dies könnte ein Sicherheitsrisiko für ihren Server darstellen, und wir möchten das wirklich nicht.

Normalerweise verwendet der PDF Drucker den Benutzerkontext des Druckbenutzers, um die PDF-Erstellung durchzuführen. Dies ist sehr sinnvoll, wenn sie es auf einem Desktop PC oder einem Terminalserver agieren. Selbst wenn sie es von einem normalen Dienst aus verwenden, kann es von Vorteil sein, die Konvertierung im Kontext des Dienstbenutzers auszuführen. Wenn sie den IIS betrachten, ist der Benutzerkontext jedoch zu stark gesperrt. Ihre Besucher von der Website sind möglicherweise anonym und wir können uns daher nicht auf den normalen Sicherheitskontext verlassen.

Glücklicherweise kann der PDF Drucker so konfiguriert werden, dass er im Sicherheitskontext des Print Spooler-Dienstes ausgeführt wird. Dieser Dienst verwendet normalerweise das Systemkonto, um sich anzumelden. Das Systemkonto hat Zugriff auf die meisten lokalen Ressourcen, z. B. lokale Festplatten. Um den Drucker für die Ausführung im Spooler-Kontext zu konfigurieren, müssen einige Registrierungseinstellungen vorgenommen werden. Anstatt dies manuell durchführen zu müssen, verfügt das Drucker-Setup-Programm über einen Befehlszeilenschalter, der ihn anweist, einen Drucker zu installieren und ihn für die Verwendung mit IIS vorzubereiten.

Drucken und Parallelisierung

Wenn ein Benutzer ihre Website besucht und ein PDF-Dokument erhalten möchte, starten sie einen Prozess, der das angeforderte Dokument erstellt. Ein anderer Benutzer könnte zu ihrer Website kommen und ein anderes PDF anfordern, während das erste noch produziert wird.

Normalerweise wird der Drucker durch Erstellen einer Konfigurationsdatei runonce.ini gesteuert. Diese Datei legt die Parameter für die Erstellung des nächsten PDF-Druckauftrags fest. Bei gleichzeitigen Benutzern kann dieses Verhalten nicht weiter verwendet werden, da eine runonce.ini eine andere überschreiben kann, die noch nicht vom Drucker verarbeitet wurde. Daher müssen wir im PDF Drucker eine Funktion verwenden, mit der wir dem Drucker genau mitteilen können, welche Runonce-Konfiguration für einen bestimmten Druckauftrag verwendet werden soll.

Das Beispiel ausführen

So installieren Sie den Drucker und richten die ASP.NET-Anwendung ein.

Installieren des PDF-Druckers

Um dieses Beispiel auszuführen, müssen sie zunächst den PDF Drucker installieren und ihn für die Verwendung mit IIS vorbereiten. Denken sie daran, dass sie Version 10.8 und mindestens das Professional Setup oder höher verwenden müssen, damit dies funktioniert. Auch wenn sie den Drucker bereits installiert haben, empfehlen wir ihnen, diese neue Instanz des Druckers zu installieren und speziell für die Verwendung mit IIS zu konfigurieren. Um diese Aufgaben auszuführen, führen sie einfach die folgende Befehlszeile in einem Ordner aus, in dem sich das Setup-Programm für den Drucker befindet:

Setup_7PDF_10_8_0_2277_PRO.exe /SPOOLERCONTEXT /SILENT /PRINTERNAME="IIS PDF Printer"

Dadurch werden die richtigen Registrierungseinträge festgelegt und eine Ordnerstruktur für Dateien erstellt, die sich auf die PDF-Erstellung beziehen. Standardmäßig werden diese Dateien und Ordner hier erstellt:

C:\ProgramData\PDF Writer\IIS PDF Printer

Erstellen Sie die ASP.NET-Anwendung

Sie müssen die Beispieldateien herunterladen und den Ordner als IIS-Anwendung mit Unterstützung für ASP.NET registrieren. Denken Sie daran, den Ordner APP_DATA für den Benutzer der APS.NET-Anwendung schreibbar zu machen.

Wenn die Anwendung erstellt und der Drucker installiert ist, können Sie zu Default.aspx wechseln und das Beispiel ausprobieren.

Der Quellcode

Sie können den Quellcode für dieses Beispiel in der folgenden ZIP-Datei herunterladen oder sich von der Quellcode Auflistung inspirieren lassen.

    <%@ WebHandler Language="C#" Class="Print" %>
    
    using System;
    using System.Web;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Drawing.Printing;
    using System.IO;
    using System.Linq;
    using pdf7.PdfWriter;
    
    public class Print : IHttpHandler
    {
    
        public void ProcessRequest(HttpContext context)
        {
            string printerName = "IIS PDF Printer";
            string downloadName = "aspnet test.pdf";
            string jobId = Guid.NewGuid().ToString();
            string jobName = string.Format("ASP.NET-{0}", jobId);
            string tempPath = Path.Combine(HttpContext.Current.Server.MapPath("~/App_Data"), 
                "Temp");
            string jobTempPath = Path.Combine(tempPath, jobId);
            string pdfName = string.Format("ASP.NET-{0}.pdf", jobId);
            string pdfPath = Path.Combine(jobTempPath, pdfName);
            string statusFile = Path.Combine(jobTempPath, "status.ini");
    
            // Create folders
            Directory.CreateDirectory(jobTempPath);
    
            // Set parameters for print job
            PdfSettings pdfSettings = new PdfSettings();
            pdfSettings.PrinterName = printerName;
    
            // These settings will only have effect if they are not overwritten by values in 
            // the global.ini
            pdfSettings.SetValue("Output", pdfPath);
            pdfSettings.SetValue("StatusFile", statusFile);
            pdfSettings.SetValue("ShowSettings", "never");
            pdfSettings.SetValue("ShowSaveAS", "never");
            pdfSettings.SetValue("ShowProgress", "no");
            pdfSettings.SetValue("ShowProgressFinished", "no");
            pdfSettings.SetValue("ShowPDF", "no");
            pdfSettings.SetValue("ConfirmOverwrite", "no");
            pdfSettings.SetValue("RememberLastFolderName", "no");
            pdfSettings.SetValue("RememberLastFileName", "no");
            pdfSettings.SetValue("WatermarkLayer", "bottom");
            pdfSettings.SetValue("WatermarkText", "Test from ASP.NET");
    
            // Create a runonce.ini that is specific to this job
            // https://www.7-pdf.com/products/pdf-printer/documentation/settings
            string defaultRunoncePath = 
                pdfSettings.GetSettingsFilePath(PdfSettingsFileType.RunOnce);
            string specificRunoncePath = Path.Combine(
                Path.GetDirectoryName(defaultRunoncePath), 
                string.Format("runonce_{0}.ini", Uri.EscapeDataString(jobName)));
            pdfSettings.WriteSettings(specificRunoncePath);
    
            // Create print job
            PrintDocument pd = new PrintDocument();
            pd.DocumentName = jobName;
            pd.PrintPage += new PrintPageEventHandler(this.pd_PrintPage);
            pd.PrinterSettings.PrinterName = printerName;
            pd.DefaultPageSettings.Landscape = false;
            pd.DefaultPageSettings.PaperSize = new PaperSize("Letter", 850, 1100);
            pd.Print();
    
            // Wait for PDF creation to finish
            if (PdfUtil.WaitForFile(statusFile, 20000))
            {
                // Read error information from status file
                string errorValue = PdfUtil.ReadIniString(statusFile, "Status", "Errors", 
                    "");
    
                if (errorValue == "0")
                {
                    // Stream PDF to browser
                    context.Response.ClearContent();
                    context.Response.ContentType = "Application/pdf";
                    context.Response.AddHeader("Content-Disposition", 
                        "inline; filename=" + downloadName);
                    context.Response.WriteFile(pdfPath);
                    context.Response.Flush();
    
                    // Remove files after the PDF is streamed to the client browser
                    File.Delete(pdfPath);
                    File.Delete(statusFile);
                    Directory.Delete(jobTempPath);
                    
                    context.Response.End();
                    return;
                }
                else
                {
                    string errorMessage = PdfUtil.ReadIniString(statusFile, "Status", 
                        "MessageText", "");
                    WriteErrorMessage(string.Format("An error was reported: {0}; {1}", 
                        errorValue, errorMessage));
                }
            }
            WriteErrorMessage("No PDF was created.");
        }
    
        private void WriteErrorMessage(string message)
        {
            HttpContext.Current.Response.ContentType = "text/plain";
            HttpContext.Current.Response.Write(message);
        }
    
        private void pd_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
        {
            // Output something in the print
            SolidBrush myBrush = new SolidBrush(Color.Blue);
            Font font = new Font("Arial", 12);
            e.Graphics.DrawString("Print test: " + DateTime.Now.ToString(),
             font, myBrush, e.MarginBounds.Left, e.MarginBounds.Top);
            myBrush.Dispose();
        }
    
        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
    

Fehlerbehebung

Wenn sie keinen Schreibzugriff für den IIS-Benutzer oder die Benutzer im Allgemeinen im Ordner APP_DATA festgelegt haben, wird ein ähnlicher Fehler angezeigt, wie: Access to the path 'C:\inetpub\Print From Handler\App_Data\Temp\b2c27634-1ee5-4afc-a4da-0f93c7b2452f' is denied.

Sie können das Beispiel selbst herunterladen und ausführen. Die benötigten Dateien sind hier verfügbar.

Downloads

Anhang Größe
Codebeispiel herunterladen 8.7 KB

Top