|
|
Problem mit großer PDF-Datei via ashx-Handler
Letzter Beitrag 03-30-2012, 12:42 von Stefan Falz. 8 Antworten.
-
03-13-2012, 11:59 |
-
Bumbum
-
-
-
-
Registriert am 11-14-2007
-
Würzburg
-
Beiträge 235
-
-
|
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 |
-
Stefan Falz
-
ASP.NET Zone Team
-
-
-
Registriert am 12-15-2000
-
-
Beiträge 7.301
-
-
|
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.NETASP.NET Consulting, Development, CoachingASP.NET Zone - Leitfaden für gute PostingsXtopia 2008 - Gewinnspiel / Expression Studio und Xtopia Eintrittskarten zu gewinnen
|
|
-
03-13-2012, 15:15 |
-
Bumbum
-
-
-
-
Registriert am 11-14-2007
-
Würzburg
-
Beiträge 235
-
-
|
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 |
-
Bumbum
-
-
-
-
Registriert am 11-14-2007
-
Würzburg
-
Beiträge 235
-
-
|
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 |
-
Stefan Falz
-
ASP.NET Zone Team
-
-
-
Registriert am 12-15-2000
-
-
Beiträge 7.301
-
-
|
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.NETASP.NET Consulting, Development, CoachingASP.NET Zone - Leitfaden für gute PostingsXtopia 2008 - Gewinnspiel / Expression Studio und Xtopia Eintrittskarten zu gewinnen
|
|
-
03-14-2012, 9:47 |
-
Bumbum
-
-
-
-
Registriert am 11-14-2007
-
Würzburg
-
Beiträge 235
-
-
|
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 |
-
Bumbum
-
-
-
-
Registriert am 11-14-2007
-
Würzburg
-
Beiträge 235
-
-
|
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 |
-
Bumbum
-
-
-
-
Registriert am 11-14-2007
-
Würzburg
-
Beiträge 235
-
-
|
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 |
|
|
|