Problems storing upload file in session (ObjectDisposedException)

J

J055

Hi

I have the following code. I upload an XML file using the FileUpload object,
store the stream in a session so the user gets the chance to confirm some
options then pass the stream from the Session to an XmlReader.

if (performImport == false)
{
Session["__xmlImportFile"] = fileUpload1.FileContent;
//... some other code
}
else
{
if (Session["__xmlImportFile"] != null)
{
Stream xmlFile = (Stream)Session["__xmlImportFile"];
xmlFile.Position = 0;
// ... pass xmlFile to XmlReader
}
Session.Remove("__xmlImportFile");
}

This works fine on the Visual Studio web server. When I transfer the code to
an IIS web server I can only get the code to work if the uploaded file is
80Kb or less. Anything over that and I get an ObjectDisposedException
(Cannot access a closed file.) The size in bytes of the stream from the
session appears to be correct before the XmlReader is called.

[ObjectDisposedException: Cannot access a closed file.]
System.IO.__Error.FileNotOpen() +56
System.IO.FileStream.Seek(Int64 offset, SeekOrigin origin) +1945963
System.Web.TempFile.GetBytes(Int32 offset, Int32 length, Byte[] buffer,
Int32 bufferOffset) +35
System.Web.HttpRawUploadedContent.CopyBytes(Int32 offset, Byte[] buffer,
Int32 bufferOffset, Int32 length) +112
System.Web.HttpInputStream.Read(Byte[] buffer, Int32 offset, Int32 count)
+47
System.Xml.XmlTextReaderImpl.InitStreamInput(Uri baseUri, String
baseUriStr, Stream stream, Byte[] bytes, Int32 byteCount, Encoding encoding)
+196
System.Xml.XmlTextReaderImpl..ctor(Stream stream, Byte[] bytes, Int32
byteCount, XmlReaderSettings settings, Uri baseUri, String baseUriStr,
XmlParserContext context, Boolean closeInput) +62
System.Xml.XmlReader.CreateReaderImpl(Stream input, XmlReaderSettings
settings, Uri baseUri, String baseUriStr, XmlParserContext inputContext,
Boolean closeInput) +68
System.Xml.XmlReader.Create(Stream input, XmlReaderSettings settings,
String baseUri) +37
System.Xml.XmlReader.Create(Stream input, XmlReaderSettings settings) +30

Can you tell me what is happening here and how I might resolve it?

Many thanks
Andrew
 
?

=?ISO-8859-1?Q?G=F6ran_Andersson?=

J055 said:
Hi

I have the following code. I upload an XML file using the FileUpload object,
store the stream in a session so the user gets the chance to confirm some
options then pass the stream from the Session to an XmlReader.

if (performImport == false)
{
Session["__xmlImportFile"] = fileUpload1.FileContent;

As you haven't created the stream yourself, you don't have control over
when the stream is disposed. When the FileUpload control is disposed, it
also disposes the stream.

If you need to store something in a session variable, you have to store
the actual content of the file, not the stream used to read it.

Generally it's a bad idea to store large objects in session variables,
though. It uses up memory, and that is a limited resource on the server.
You should consider other options for storing it.
//... some other code
}
else
{
if (Session["__xmlImportFile"] != null)
{
Stream xmlFile = (Stream)Session["__xmlImportFile"];
xmlFile.Position = 0;
// ... pass xmlFile to XmlReader
}
Session.Remove("__xmlImportFile");
}

This works fine on the Visual Studio web server.

No, not fine. You just got lucky (?) that it didn't blow up.
When I transfer the code to
an IIS web server I can only get the code to work if the uploaded file is
80Kb or less. Anything over that and I get an ObjectDisposedException
(Cannot access a closed file.) The size in bytes of the stream from the
session appears to be correct before the XmlReader is called.

[ObjectDisposedException: Cannot access a closed file.]
System.IO.__Error.FileNotOpen() +56
System.IO.FileStream.Seek(Int64 offset, SeekOrigin origin) +1945963
System.Web.TempFile.GetBytes(Int32 offset, Int32 length, Byte[] buffer,
Int32 bufferOffset) +35
System.Web.HttpRawUploadedContent.CopyBytes(Int32 offset, Byte[] buffer,
Int32 bufferOffset, Int32 length) +112
System.Web.HttpInputStream.Read(Byte[] buffer, Int32 offset, Int32 count)
+47
System.Xml.XmlTextReaderImpl.InitStreamInput(Uri baseUri, String
baseUriStr, Stream stream, Byte[] bytes, Int32 byteCount, Encoding encoding)
+196
System.Xml.XmlTextReaderImpl..ctor(Stream stream, Byte[] bytes, Int32
byteCount, XmlReaderSettings settings, Uri baseUri, String baseUriStr,
XmlParserContext context, Boolean closeInput) +62
System.Xml.XmlReader.CreateReaderImpl(Stream input, XmlReaderSettings
settings, Uri baseUri, String baseUriStr, XmlParserContext inputContext,
Boolean closeInput) +68
System.Xml.XmlReader.Create(Stream input, XmlReaderSettings settings,
String baseUri) +37
System.Xml.XmlReader.Create(Stream input, XmlReaderSettings settings) +30

Can you tell me what is happening here and how I might resolve it?

Many thanks
Andrew
 
B

bruce barker

when the request completes, the stream is closed, so storing in session
is useless. if small, you could read the stream into sring, or into a
dom and store in session

-- bruce (sqlwork.com)
 
G

Guest

As Goran indicated, you might want to try this approach, which stores the
contents (that's what you want anyway, right?):

Int32 fileLen;
// Get the length of the file.
fileLen = FileUpload1.PostedFile.ContentLength;
// Create a byte array to hold the contents of the file.
Byte[] Input = new Byte[fileLen];
// Initialize the stream to read the uploaded file.
myStream = FileUpload1.FileContent;
// Read the file into the byte array.
myStream.Read(Input, 0, fileLen);
// Store the byte array in Session
Session["__xmlImportFileBytes"] = Input;

--Peter
Recursion: see Recursion
site: http://www.eggheadcafe.com
unBlog: http://petesbloggerama.blogspot.com
bogMetaFinder: http://www.blogmetafinder.com



J055 said:
Hi

I have the following code. I upload an XML file using the FileUpload object,
store the stream in a session so the user gets the chance to confirm some
options then pass the stream from the Session to an XmlReader.

if (performImport == false)
{
Session["__xmlImportFile"] = fileUpload1.FileContent;
//... some other code
}
else
{
if (Session["__xmlImportFile"] != null)
{
Stream xmlFile = (Stream)Session["__xmlImportFile"];
xmlFile.Position = 0;
// ... pass xmlFile to XmlReader
}
Session.Remove("__xmlImportFile");
}

This works fine on the Visual Studio web server. When I transfer the code to
an IIS web server I can only get the code to work if the uploaded file is
80Kb or less. Anything over that and I get an ObjectDisposedException
(Cannot access a closed file.) The size in bytes of the stream from the
session appears to be correct before the XmlReader is called.

[ObjectDisposedException: Cannot access a closed file.]
System.IO.__Error.FileNotOpen() +56
System.IO.FileStream.Seek(Int64 offset, SeekOrigin origin) +1945963
System.Web.TempFile.GetBytes(Int32 offset, Int32 length, Byte[] buffer,
Int32 bufferOffset) +35
System.Web.HttpRawUploadedContent.CopyBytes(Int32 offset, Byte[] buffer,
Int32 bufferOffset, Int32 length) +112
System.Web.HttpInputStream.Read(Byte[] buffer, Int32 offset, Int32 count)
+47
System.Xml.XmlTextReaderImpl.InitStreamInput(Uri baseUri, String
baseUriStr, Stream stream, Byte[] bytes, Int32 byteCount, Encoding encoding)
+196
System.Xml.XmlTextReaderImpl..ctor(Stream stream, Byte[] bytes, Int32
byteCount, XmlReaderSettings settings, Uri baseUri, String baseUriStr,
XmlParserContext context, Boolean closeInput) +62
System.Xml.XmlReader.CreateReaderImpl(Stream input, XmlReaderSettings
settings, Uri baseUri, String baseUriStr, XmlParserContext inputContext,
Boolean closeInput) +68
System.Xml.XmlReader.Create(Stream input, XmlReaderSettings settings,
String baseUri) +37
System.Xml.XmlReader.Create(Stream input, XmlReaderSettings settings) +30

Can you tell me what is happening here and how I might resolve it?

Many thanks
Andrew
 
G

Guest

Peter said:
As Goran indicated, you might want to try this approach, which stores the
contents (that's what you want anyway, right?):

Int32 fileLen;
// Get the length of the file.
fileLen = FileUpload1.PostedFile.ContentLength;
// Create a byte array to hold the contents of the file.
Byte[] Input = new Byte[fileLen];
// Initialize the stream to read the uploaded file.
myStream = FileUpload1.FileContent;
// Read the file into the byte array.
myStream.Read(Input, 0, fileLen);

Oops! ;)

The Read method returns the actual number of bytes read, which may be
less than the number of bytes requested. You have to loop until you have
read all the bytes, i.e. until Read returns zero.
// Store the byte array in Session
Session["__xmlImportFileBytes"] = Input;

--Peter
Recursion: see Recursion
site: http://www.eggheadcafe.com
unBlog: http://petesbloggerama.blogspot.com
bogMetaFinder: http://www.blogmetafinder.com
 
S

Steven Cheng[MSFT]

Hi Andrew,

As other members have mentioned, storing the Stream object directly in
Session is not a safe approach as you can not predict or confirm when the
stream will be closed or disposed. And the behavior vary much between VS
2005 web test server and IIS hosting context. For your scenario, you can
consider the following approachs:

1. Read out the actual binary content(byte array) from the stream and store
the binary content into session state. However, as others have said, this
is not quite a good way since it will cause session state memory
pressure(when there is many large files stored at the same time).

2. You can consider save uploaded file into a temp dir(in a temp file). And
in the session state, you simply store the path and file name of the temp
file.

How do you think?

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


This posting is provided "AS IS" with no warranties, and confers no rights.
 
J

J055

Hi

Thanks to everyone for there assistance. It makes sense to me now about the
stream being disposed of outside my control. The reason I thought it OK to
store a stream in a Session is simply because it's is a very occasional
demand on the system for our application.

I've decided to store the file on disk, however. I found the
Path.GetTempFileName method very useful for this.

Many thanks
Andrew
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,990
Messages
2,570,211
Members
46,799
Latest member
Mercury_Dev

Latest Threads

Top