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:
- es wurden nicht sehr viele gleichzeitige Zugriffe erwartet,
- der Server, auf dem die Anwendung laufen wird, hat ausreichend freie Ressourcen,
- die Dateigröße für Uploads war sowieso auf wenige Megabytes beschränkt.
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.