ASP.NET Zone

Die ASP.NET Community. Alle Antworten rund um Microsoft® Webtechnologien
Willkommen bei ASP.NET Zone. Anmelden | Registrieren | Hilfe | Impressum | ASP.NET Zone Suchplugin

in
Home Blogs Foren FAQ Communities Fotos Downloads
Werbeanzeige

Problem mit großer PDF-Datei via ashx-Handler

Letzter Beitrag 03-30-2012, 12:42 von Stefan Falz. 8 Antworten.
Beiträge sortieren: Zurück Weiter
  •  03-13-2012, 11:59 224043

    Problem mit großer PDF-Datei via ashx-Handler

    Hallo,

    große Dateien für Intranet-Anwendungen sind im IIS wohl nicht standardmäßig vorgesehen... Erst hatte ich Probleme mit dem Upload, der jetzt aber funktioniert. (siehe anderer Thread)

    Aber jetzt gibt es auch Probleme mit dem download. Wenn ich meine Anwendung in Visual-Studio laufen lasse, kann ich die 10 MB große PDF-Datei problemlos herunterladen und sie wird auch korrekt im Browser angezeigt. Die Datei wird per ashx-Handler bereit gestellt.

    Wenn ich das ganze über den IIS 6.0 unseres SBS2003 im Intranet versuche sehe ich das Acrobat-Plugin im Browser mit dem download-Balken, der aber dann immer bei ca. 3MB bis ca. 5MB stehen bleibt, jedes mal an einer anderen Stelle.

    Was könnte nun wieder schief laufen?

    Viele Grüße

    Andreas

  •  03-13-2012, 12:39 224044 Antwort zu 224043

    AW: Problem mit großer PDF-Datei via ashx-Handler

    Hallo Andreas,

    Bumbum:

    Aber jetzt gibt es auch Probleme mit dem download. Wenn ich meine Anwendung in Visual-Studio laufen lasse, kann ich die 10 MB große PDF-Datei problemlos herunterladen und sie wird auch korrekt im Browser angezeigt. Die Datei wird per ashx-Handler bereit gestellt.

    Wie schon mal gesagt: Schmeiß den ASP.NET Entwicklungswebserver weg und verwende auch lokal den IIS zum entwickeln. Damit hast Du einige solcher Problemstellen nicht mehr. (Damit meine ich die Unterschiede zwischen dem integrierten Entwicklungswebserver und dem IIS)

    Bumbum:

    Wenn ich das ganze über den IIS 6.0 unseres SBS2003 im Intranet versuche sehe ich das Acrobat-Plugin im Browser mit dem download-Balken, der aber dann immer bei ca. 3MB bis ca. 5MB stehen bleibt, jedes mal an einer anderen Stelle.

    Am IIS liegt das nicht, eher an deinem Code oder, was ich für noch wahrscheinlicher halte, an etwas zwischen Webserver und Client (bspw. Firewall, lokale Sicherheitssoftware, ...)

    Um den Code auszuschließen, poste bitte mal den relevanten Teil der ASHX, mit der Du die Datei sendest.


    --
    Gruß, Stefan Falz
    Microsoft MVP - Visual Developer ASP/ASP.NET
    ASP.NET Consulting, Development, Coaching

    ASP.NET Zone - Leitfaden für gute Postings

    Xtopia 2008 - Gewinnspiel / Expression Studio und Xtopia Eintrittskarten zu gewinnen
  •  03-13-2012, 15:15 224046 Antwort zu 224044

    AW: Problem mit großer PDF-Datei via ashx-Handler

    Hallo Stefan,

    Stefan Falz:

    Wie schon mal gesagt: Schmeiß den ASP.NET Entwicklungswebserver weg und verwende auch lokal den IIS zum entwickeln. Damit hast Du einige solcher Problemstellen nicht mehr. (Damit meine ich die Unterschiede zwischen dem integrierten Entwicklungswebserver und dem IIS)

    Jetzt habe ich deinen Satz bewußt wahrgenommen. Im anderen Thema ist dieser irgendwie nicht "bleibend" hängen geblieben. Daran kämpfe ich gerade. Ich habe auf meinem System den IIS nachinstalliert und versucht die Seite dort zum laufen zu bekommen. Da happert es aber aktuell noch ("Fehler beim Zugriff auf die IIS-Metabasis". Die Google-Lösung dafür lautet aspnet_iisreg -i -enable, aber das hilft irgendwie nicht. Aber dies ist ein anderes Thema und falls ich damit nicht klar komme melde ich mich noch mal mit einem neuen Thread zu diesem Thema.)

    Stefan Falz:

    Am IIS liegt das nicht, eher an deinem Code oder, was ich für noch wahrscheinlicher halte, an etwas zwischen Webserver und Client (bspw. Firewall, lokale Sicherheitssoftware, ...)

    Um den Code auszuschließen, poste bitte mal den relevanten Teil der ASHX, mit der Du die Datei sendest.

    Als Firewall ist nur die Windows-Eigene installiert. Diese kann ich aber wegen Domänen-Richtlinien nicht deaktivieren, zumindest nicht so einfach. Als sonstigen Schutz haben wir nur noch Kaspersky laufen, diesen habe ich aber testweise abgeschaltet. Ich werde später von zuhause aus mal versuchen auf die Webseite zuzugreifen, mal schauen ob es von dort läuft.

    Bis dann mein IIS hier läuft, oder ich zuhause getestet habe stelle ich mal den Code des File-Handlers hier ein. Vielleicht fällt euch ja was auf, obwohl da eigentlich nichts besonderes drin ist. Die PDF-Datei kommt aus einer MySQL-Datenbank:



    Imports Microsoft.VisualBasic
    Imports System.Threading

    Public Class FileHandler
        Implements IHttpAsyncHandler, IRequiresSessionState

        Public Const Erweiterungen As String = "PDF,CSV,XLS,XLSX,DOC,DOCX,ZIP,DAT,TXT"
        Public Const ContentTypes As String = "application/pdf,application/csv,application/vnd.ms-excel,application/vnd.ms-excel,application/msword,application/msword,application/x-zip-compressed,application/octet-stream,text/plain"

        Public ReadOnly Property IsReusable() As Boolean Implements System.Web.IHttpHandler.IsReusable
            Get
                Return False
            End Get
        End Property

        Public Function BeginProcessRequest(ByVal context As System.Web.HttpContext, ByVal cb As System.AsyncCallback, ByVal extraData As Object) As System.IAsyncResult Implements System.Web.IHttpAsyncHandler.BeginProcessRequest
            Dim asynch As New AsynchOperation(cb, context, extraData)

            asynch.StartAsyncWork()
            Return asynch
        End Function

        Public Sub EndProcessRequest(ByVal result As System.IAsyncResult) Implements System.Web.IHttpAsyncHandler.EndProcessRequest

        End Sub

        Public Sub ProcessRequest(ByVal context As System.Web.HttpContext) Implements System.Web.IHttpHandler.ProcessRequest

        End Sub

     

        Private Class AsynchOperation
            Implements IAsyncResult

            Private completed As Boolean
            Private state As [Object]
            Private callback As AsyncCallback
            Private context As HttpContext

            ReadOnly Property IsCompleted() As Boolean Implements IAsyncResult.IsCompleted
                Get
                    Return completed
                End Get
            End Property

            ReadOnly Property AsyncWaitHandle() As WaitHandle Implements IAsyncResult.AsyncWaitHandle
                Get
                    Return Nothing
                End Get
            End Property

            ReadOnly Property AsyncState() As [Object] Implements IAsyncResult.AsyncState
                Get
                    Return state
                End Get
            End Property

            ReadOnly Property CompletedSynchronously() As Boolean Implements IAsyncResult.CompletedSynchronously
                Get
                    Return False
                End Get
            End Property

            Public Sub New(ByVal callback As AsyncCallback, ByVal context As HttpContext, ByVal state As [Object])
                Me.callback = callback
                Me.context = context
                Me.state = state
                Me.completed = False
            End Sub

            Public Sub StartAsyncWork()
                ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf StartAsyncTask), Nothing)
            End Sub

            Private Sub StartAsyncTask(ByVal workItemState As [Object])
                Dim AppSession As New clsSession(context.Session)

                If AppSession.CurrentUser_ID > 0 Then
                    Dim FileName As String = context.Request.FilePath
                    Dim tmpPos As Long = InStrRev(FileName, "/")
                    If tmpPos > 0 Then FileName = FileName.Substring(tmpPos, FileName.Length - tmpPos).ToUpper

                    Dim DokumentID As Long = Val(context.Request.Params("DokumentID"))

                    If DokumentID > 0 Then
                        Using DB As New clsMySQL
                            Dim tmpDokument As New clsTBData.Dokument(DB)

                            If tmpDokument.DBread(DokumentID) Then
                                If tmpDokument.DateiName.ToUpper = FileName Then
                                    Dim tmpGebiet As New clsTBData.Gebiet(DB)

                                    If tmpGebiet.DBread(tmpDokument.Gebiet) Then
                                        If tmpGebiet.Firma = AppSession.CurrentFirma_ID Then
                                            context.Response.Clear()

                                            Dim Extension As String = ""
                                            tmpPos = InStrRev(FileName, ".")
                                            If tmpPos > 0 Then Extension = FileName.Substring(tmpPos, FileName.Length - tmpPos)

                                            Dim Extensions() As String = Split(FileHandler.Erweiterungen, ",")
                                            Dim Types() As String = Split(FileHandler.ContentTypes, ",")
                                            Dim i1 As Long

                                            For i1 = 0 To UBound(Extensions)
                                                If Extension = Extensions(i1) Then
                                                    context.Response.ContentType = ContentTypes(i1)
                                                    context.Response.BinaryWrite(tmpDokument.DateiData)
                                                    Exit For
                                                End If
                                            Next
                                        End If
                                    End If
                                End If
                            End If
                        End Using
                    End If
                End If

                completed = True
                callback(Me)
            End Sub
        End Class
    End Class

    Viele Grüße

    Andreas

  •  03-13-2012, 16:52 224047 Antwort zu 224046

    AW: Problem mit großer PDF-Datei via ashx-Handler

    Hallo,

    ich habe mehr Informationen zum Problem. Aber vorab: Falls jemand per Google auf das Stichtwort "Fehler beim Zugriff auf die IIS-Metabasis" hier trifft und die Lösung mit dem "aspnet_regiis.exe -i -enable" auch nicht hilft: Von Microsoft gibt es ein Script (metaacl.vbs). Mit diesem kann man einem Benutzerkonto Berechtigungen auf die Metabasis geben. Ich habe auf meinem Computer unter Systemsteuerung/Benutzer nachgeschaut, welches das ASPNET-Konto sein könnte. (Bei mir war hieß der Benutzer einfach ASPNET) und habe dann mit dem Script die Berechtigungen an diesen Benutzer vergeben und die Seite läuft nun im IIS 5.1 von Windows XP.

    Zurück zu meinem Problem: Erstaunlicherweise funktioniert über den IIS 5.1 von Windows XP der download der PDF-Datei genauso wie mit dem Developement-Server des Visual-Studio.

    Einen Unterscheid habe ich aber zum IIS 6.0 auf unserm SBS2003 bemerkt: Das Adobe-Plugin zeigt beim download einen Fortschrittsbalken an. Dabei wird sowohl im IIS 5.1 von XP, als auch im VS-Server die Dateigröße angezeigt. Wenn ich das gleiche aber über den IIS 6.0 mache steht dort z.B 3,9MB/0,0kB.

    Ich habe auch festgestellt, das grundsätzlich keine PDF-Dateien über den IIS 6.0 über den Filehandler geladen werden können. Auch nicht wenn diese eine Dateigröße von 100kB oder weniger haben.

    Mit z.B. Excel-Dateien funktioniert alles. Ich kann die PDF-Datei über den IIS 6.0 ohne Probleme mit Ziel speichern unter auf meiner Festplatte speichern, und ich kann die Datei danach auch öffnen.

    Die Frage ist nun warum klappt nur im IIS 6.0 der Direktlink nicht? Warum wird vor allem auch keine Dateigröße angezeigt? Beim download mit Ziel speichern unter wird auch keine Größe und somit keine Zeitschätzung angegeben. Anders als beim IIS 5.1 oder dem VS-Server. Hier ist die Dateigröße von vorn herein bekannt.

    Viele Grüße

    Andreas

  •  03-13-2012, 17:08 224048 Antwort zu 224046

    AW: Problem mit großer PDF-Datei via ashx-Handler

    Hallo Andreas,

    Bumbum:

    Bis dann mein IIS hier läuft, oder ich zuhause getestet habe stelle ich mal den Code des File-Handlers hier ein. Vielleicht fällt euch ja was auf, obwohl da eigentlich nichts besonderes drin ist.

    also mir fällt da was auf. Der Async Handler ist hier IMHO völlig fehl am Platz. Ändere das so ab, dass hier synchron gearbeitet wird. (Also eigentlich alles, was mit Async zu tun hat, rausschmeißen).

    Grundsätzlich sind asynchrone Aufgaben Ok, für die Anforderung, eine Datei herunterzuladen aber eher nicht.



    --
    Gruß, Stefan Falz
    Microsoft MVP - Visual Developer ASP/ASP.NET
    ASP.NET Consulting, Development, Coaching

    ASP.NET Zone - Leitfaden für gute Postings

    Xtopia 2008 - Gewinnspiel / Expression Studio und Xtopia Eintrittskarten zu gewinnen
  •  03-14-2012, 9:47 224052 Antwort zu 224048

    AW: Problem mit großer PDF-Datei via ashx-Handler

    Hallo Stefan,

    das war leider nicht die Ursache für das Problem. Das Verhalten ohne asynchronen Handler ist das gleiche. Hier mal der Code des neuen Handlers:



    Imports Microsoft.VisualBasic

    Public Class FileHandler
        Implements IHttpHandler
        Implements IRequiresSessionState

        Private Const Erweiterungen As String = "PDF,CSV,XLS,XLSX,DOC,DOCX,ZIP,DAT,TXT"
        Private Const ContentTypes As String = "application/pdf,application/csv,application/vnd.ms-excel,application/vnd.ms-excel,application/msword,application/msword,application/x-zip-compressed,application/octet-stream,text/plain"

     

        Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
            Dim AppSession As New clsSession(context.Session)

            If AppSession.CurrentUser_ID > 0 Then
                Dim FileName As String = context.Request.FilePath
                Dim tmpPos As Long = InStrRev(FileName, "/")
                If tmpPos > 0 Then FileName = FileName.Substring(tmpPos, FileName.Length - tmpPos).ToUpper

                Dim DokumentID As Long = Val(context.Request.Params("DokumentID"))

                If DokumentID > 0 Then
                    Using DB As New clsMySQL
                        Dim tmpDokument As New clsTBData.Dokument(DB)

                        If tmpDokument.DBread(DokumentID) Then
                            If tmpDokument.DateiName.ToUpper = FileName Then
                                Dim tmpGebiet As New clsTBData.Gebiet(DB)

                                If tmpGebiet.DBread(tmpDokument.Gebiet) Then
                                    If tmpGebiet.Firma = AppSession.CurrentFirma_ID Then
                                        context.Response.Clear()

                                        Dim Extension As String = ""
                                        tmpPos = InStrRev(FileName, ".")
                                        If tmpPos > 0 Then Extension = FileName.Substring(tmpPos, FileName.Length - tmpPos)

                                        Dim Extensions() As String = Split(FileHandler.Erweiterungen, ",")
                                        Dim Types() As String = Split(FileHandler.ContentTypes, ",")
                                        Dim i1 As Long

                                        For i1 = 0 To UBound(Extensions)
                                            If Extension = Extensions(i1) Then
                                                context.Response.ContentType = ContentTypes(i1)
                                                context.Response.BinaryWrite(tmpDokument.DateiData)
                                                Exit For
                                            End If
                                        Next
                                    End If
                                End If
                            End If
                        End If
                    End Using
                End If
            End If
        End Sub

        Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
            Get
                Return False
            End Get
        End Property
    End Class

    Viele Grüße

    Andreas

  •  03-15-2012, 14:23 224060 Antwort zu 224052

    AW: Problem mit großer PDF-Datei via ashx-Handler

    Hallo,

    ich habe etwas weiter geforscht. Es betrifft nur PDF-Dateien. Alle anderen funktionieren einwandfrei. PDF gehen dafür überhaupt nicht, egal welche Größe. Es gibt bei Google sehr viele Treffer für das Problem von PDF-Dateien über ASHX-Handler, aber nur mit dem IIS7 oder IIS7.5. Im Zusammenhang mit dem von mir verwendeten IIS6 habe ich nichts gefunden.

    Ich habe auch verschiedene Browser versucht. Es geht definitiv nicht, wenn die Seite im IIS6 gehostet wird.

    Daraufhin habe ich am Filehandler herumprobiert und ihn wie folgt erweitert:



    context.Response.Clear()
    context.Response.BufferOutput = False
    context.Response.AddHeader("Content-Disposition", "attachment;filename=""" & tmpDokument.DateiName & """")
    context.Response.AddHeader("Content-Length", Trim$(Str$(tmpDokument.DateiGröße)))
    context.Response.ContentType = ContentTypes(i1)
    context.Response.BinaryWrite(tmpDokument.DateiData)
    context.Response.Flush()
    context.Response.End()

    Es wird zwar trotz Header Content-Length immer noch nicht die Größe beim download angezeigt, aber es funktioniert trotzdem grundsätzlich, da wegen des Content-Disposition vom Browser immer gefragt wird, ob die Datei geöffnet oder gespeichert werden soll. Wenn man öffnen klickt wird die Datei erst vom Browser heruntergeladen und dann ganz normal im Acrobat-Reader geöffnet, anstatt im Plugin für den Browser. Das funktioniert, ist aber nur ein Workaround.

    Woran kann es liegen, dass der IIS6 keine Dateigröße beim ASHX-Handler mitliefert? Ich vermute, wenn dieses "Problem" gelöst ist, funktioniert auch das PDF-Plugin der Browser.

    Viele Grüße

    Andreas

  •  03-28-2012, 11:49 224105 Antwort zu 224060

    AW: Problem mit großer PDF-Datei via ashx-Handler

    Hallo,

    ich grabe dieses Thema mal wieder aus. Ich habe etwas weiter experimentiert. Wenn ich den Handler umschreibe, dass er die Daten aus einer Datei liest, funktioniert das Ganze auch aus dem IIS 6.0 unseres SBS2003:



        Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
            Dim FileName As String = context.Server.MapPath(context.Request.FilePath)
            Dim Source As New System.IO.FileStream(FileName, IO.FileMode.Open)
            Dim FileSize As Long = Source.Length

            context.Response.Clear()
            context.Response.AddHeader("Content-Length", Trim$(Str$(FileSize)))
            context.Response.ContentType = "application/pdf"
            context.Response.Buffer = False
            context.Response.Flush()

            Dim Buffer(FileSize) As Byte
            Source.Read(Buffer, 0, FileSize)
            Source.Close()

            context.Response.OutputStream.Write(Buffer, 0, FileSize)
            context.Response.OutputStream.Flush()
            context.Response.OutputStream.Close()
            context.Response.End()
        End Sub

    Wenn ich den Inhalt des Buffers allerdings aus meiner Datenbank lese, funktioniert das ganze nicht. Hier noch mal der entscheidende Code-Teil:

    context.Response.Clear() 
    'context.Response.AddHeader("Content-Disposition", "attachment;filename=""" & tmpDokument.DateiName & """")
    context.Response.AddHeader("Content-Length", Trim$(Str$(tmpDokument.DateiGröße)))
    context.Response.ContentType = ContentTypes(i1)
    context.Response.BufferOutput = False
    context.Response.Flush()

    context.Response.OutputStream.Write(tmpDokument.DateiData, 0, tmpDokument.DateiGröße)
    context.Response.OutputStream.Flush()
    context.Response.OutputStream.Close()
    context.Response.End()

    Das ist doch total seltsam, vor allem da es aus Visual Studio funktioniert, und auch wenn ich mit meinem IIS 5.1 aus Windows XP debugge.

    Wenn ich die auskommentierte Zeile oben ("Content-Disposition") aktiviere fragt mich der Browser ob ich die Datei öffnen oder speichern möchte. Wenn ich auf Öffnen klicke geht diese auch auf und wird fehlerfrei dargestellt. Also denke ich, dass der Byte-Stream aus der Datenbank in Ordnung sein muss.

    Und es betrifft nur PDF-Dateien. Hat vielleicht noch jemand eine Idee dazu? Was macht der IIS 5.1 anders wie der IIS 6.0 im Bezug auf oben gezeigten Code im .net Framework 2.0?

    Viele Grüße

    Andreas

  •  03-30-2012, 12:42 224114 Antwort zu 224105

    AW: Problem mit großer PDF-Datei via ashx-Handler

    Hi,

    hast Du mal beide Inhalte und Dateigrößenangaben (also das, was Du über OutputStream.Write sendest, genau verglichen? Gibt es da einen Unterschied (ein Byte mehr oder weniger reicht aus, um den Dateiinhalt zu "zerstören")?


    --
    Gruß, Stefan Falz
    Microsoft MVP - Visual Developer ASP/ASP.NET
    ASP.NET Consulting, Development, Coaching

    ASP.NET Zone - Leitfaden für gute Postings

    Xtopia 2008 - Gewinnspiel / Expression Studio und Xtopia Eintrittskarten zu gewinnen
Als RSS Feed in XML ansehen
Powered by Community Server (Commercial Edition)