Thomas Bandt

Über mich | Kontakt | Archiv

ASP.NET - "Auf eine geschlossene Datei kann nicht zugegriffen werden"

Folgender Fehler begegnete mir letzte Woche Freitag kurz vor Feierabend:

"Auf eine geschlossene Datei kann nicht zugegriffen werden. Ausnahmedetails: System.ObjectDisposedException: Auf eine geschlossene Datei kann nicht zugegriffen werden."

Was war passiert?

Eigentlich nicht viel. Ich hatte mich ein paar Wochen zuvor das erste Mal überhaupt dafür entschieden, eine vom User hochgeladene Datei für einen kurzen Zeitraum in einer Session zu speichern. Was mir zunächst etwas Bauchschmerzen bereitete, weil ich solchen Dingen grundsätzlich kritisch gegenüberstehe, erwies sich dann aber recht schnell als sehr praktisch, denn die Bedingungen erschienen ideal:

Also speicherte ich die Files im Session-Objekt und war mit dem einfachen Handling schnell glücklich, denn unter meiner Testumgebung mit dem Visual-Studio-Webserver funktionierte alles. Später konnte man es ja immer nochmal ändern (ja, klar ;-)).

Freitag Abend installierte ich die Anwendung für erste Versuche dann auf dem Live-Webserver, einer Windows-Server-2008-Kiste mit IIS7. Und siehe da, egal was ich hochladen wollte, mir begegnete diese Fehlermeldung. Eine kurze Suche brachte mich dann zumindest mal zur Ursache:

"when the request completes, the stream is closed, so storing in session is useless."

Augenscheinlich verhält sich der VS-Webserver hier anders als der IIS7, so dass dieses Verhalten lokal kaum bis gar nicht auftritt, sondern erst unter "realen Bedingungen" (übrigens ein Grund mehr für den lokalen IIS-Einsatz).

Im Klartext: sobald der Upload abgeschlossen ist, wird der Stream - nichts anderes ist die Datei in dem Moment - geschlossen. Ein späterer Zugriff auf die SaveAs()-Methode schlägt somit fehl, auch wenn die Datei in ihren Einzelteilen noch im Speicher liegt.

Die Lösung ist einfach, und hätte mir eine Stunde Refactoring erspart, wenn ich auf mein Bauchgefühl gehört hätte - die Datei nach dem Upload direkt und sofort (zwischen-) speichern, und in der Session nur noch den Pfad als Referenz speichern.

Fazit:

Hochgeladene Dateien niemals in einer Session speichern, sondern immer gleich auf dem Filesystem ablegen.

Kommentare

  1. Marco Scheel schrieb am Dienstag, 28. April 2009 09:33:00 Uhr:

    Hi,

    auch wenn ich den Ansatz mit den Sessionvariablen nicht ganz so toll finde, kann ich verstehen, dass es unter den genannten Gründen doch ok ist ;-) Die Frage ist aber, warum du die Datei nicht aus dem Stream in ein byte[] einliest udn das in der Session speicherst? Das sollte doch funktionieren? Temporäre Daten irgendwo sind eher unschön, gerade was cleanup angeht und potentiellen Viren die dann tatsächlich auf Platte liegen? Für alle Probleme gibt es eine Lösung, frage mich nur was gegen das byte[] spricht?

    Ciao Marco
  2. Thomas schrieb am Dienstag, 28. April 2009 10:45:00 Uhr:

    Hi Marco,

    ja, das wäre eine Option gewesen. Allerdings habe ich es mir mit meiner Begründung pro Stream in Session natürlich auch ein wenig einfach gemacht - wer weiß schon auf welchem Server das später tatsächlich mal laufen wird, oder wie der Server ausgelastet ist, oder auch wie viele Leute das Ding gleichzeitig nutzen werden ...

    In Sachen Skalierbarkeit ist es also eher angeraten so wenig Resourcen wie möglich zu blockieren, und da gibt's eigentlich keine Alternative zum Filesystem.

    Und ich lösche die temp. Daten natürlich auch, wenn der Prozess vom Nutzer nicht abgeschlossen wird. Und das Risiko, dass Viren hochgeladen werden, kann man auf dem Weg sowieso nicht ausschließen, auch nicht wenn man die Bytes in der Session ablegt.


« Zurück  |  Weiter »