B
Brian Birtle
**** A CHALLENGE TO THE GURUS - refute the statement "It's impossible
to build a file upload progress meter using ASP.NET" **** First person
to prove me wrong gets "All Time .NET Programming GOD" listing in my
address book and (optionally) their name listed on my "news" page of
my birtle.com website (listed as "Jane Smith is a Programming GOD")
for at least a month. Why not take a moment to read more and possibly
boost your ego to all time highs and help me out at the same time?
I've sucessfully built a progress meter with ASP classic using
examples floating on the net, but failed using the same method using
ASP.NET. I have not seen any working upload progress meter using
ASP.NET although I have searched long and hard.
Here's the sample code that shows the "critical limitation" of ASP.NET
which seems to block all attempts at a progress meter. Note this is a
change in behavior from ASP classic:
... On_BeginRequest(...) // <-- add to your global.asax or whatever
{
////This line gets executed right when the HTTP connection is
// opened (before even any of the HTTP request is read):
Application["UploadState"] = "started";
...
////Following line thread blocks until entire request is read
// (even though I have only requested to read the first 10
// bytes of the incoming HTTP request stream (POSTed data).)
// Note this could be 30 minutes if the uploaded file is
// large and/or connection is slow. Also note that in ASP
// classic the same call will return immediately after the
// first 10 bytes are read (no thread block):
byte[] firstTenBytes = Request.BinaryRead(10);
////Following line executes only after entire HTTP request
// has been received (THAT'S A PROBLEM!):
Application["UploadState"] = "finished";
////This line would also thread block, if the BinaryRead
// line were commented out:
Stream request = Request.InputStream;
// Note I have not even called any methods on the
// InputStream - it seems the InputStream property
// itself is thread blocking.
////This line does NOT thread block...
Request.Filter = new MyFilterClass();
////...but MyFilterClass is never called by ASP.NET
// (the Read method in particular) until the entire
// request is read, thus the Filter class seems
// useless of my purposes.
} ...
In the ASP version, you stick Request.BinaryRead into a loop until you
read all the bytes. ASP classic blocks BinaryRead only until the bytes
specifed are read, so in your loop you can add a line like:
Application["BytesRead" & strUploadId] = iBytesRead
Then in a second browser window you can hit a page GetUploadStatus.asp
which would return the value of the Application variable. Please note
I have hand-coded the above, simplified example because the real code
is much more complicated and references a bunch of other classes which
would only serve as distractions and flamebait for all the
hypercritical newsreaders out there.
I also tried...
* The same code in an HttpHandler
* The same code in an XML Web Service
* The same code in various other event handlers (onload, oninit, etc.)
The problem seems to be in the HttpContext/HttpRequest classes thus no
matter where you stick the code, the thread blocking occurs.
I am trying for a 100% ASP.NET solution on the server side although if
somebody can send over some VB or C++ or whatever code that works or
even recommend another approach I'll consider you highly for
"Programming GOD" listing.
I posted this previously under the thread "Accessing
Request.InputStream / Request.BinaryRead *as the request is occuring*:
How???". Here's a few notes before you hit the reply key:
* HttpAsyncHandler appears to be used when the *response*, not the
request, is to be handled asynchronously, thus the class doesn't help.
* You cannot use Session to store the upload progress because pages
that use Session are serialized, thus the call to
GetUploadProgress.aspx in the second window would queue until the POST
acceptor main window finishes.
* The purpose is a rough estimate for an upload that would occur over
a long time (slow connection and/or very large file) thus latency
between byte sent from the client and byte received on the server and
when my thread is notified and finally round trip of the secondary
window to get the status should all be no problem. As long as the
client can see some sort of rough estimate that changes every few
seconds it's fine.
* I already searched extensively over several weeks and spent several
days trying to find a workaround and have failed. Although I am only a
humble staff programming, I am not a newbie - I have more than 6 years
experience with ASP, JSP, Java Servlets, ASP.NET, ATL C++ etc. and I'm
not often stumpted. **** Are you the programming GOD that can help me?
****
Thanks for your time.
Brian Birtle
Web Application Developer - VPD Group
International Technigroup Incorporated
http://www.iti-global.com/
http://birtle.com/
(The views above don't necessarily reflect ITI, blah blah blah...)
to build a file upload progress meter using ASP.NET" **** First person
to prove me wrong gets "All Time .NET Programming GOD" listing in my
address book and (optionally) their name listed on my "news" page of
my birtle.com website (listed as "Jane Smith is a Programming GOD")
for at least a month. Why not take a moment to read more and possibly
boost your ego to all time highs and help me out at the same time?
I've sucessfully built a progress meter with ASP classic using
examples floating on the net, but failed using the same method using
ASP.NET. I have not seen any working upload progress meter using
ASP.NET although I have searched long and hard.
Here's the sample code that shows the "critical limitation" of ASP.NET
which seems to block all attempts at a progress meter. Note this is a
change in behavior from ASP classic:
... On_BeginRequest(...) // <-- add to your global.asax or whatever
{
////This line gets executed right when the HTTP connection is
// opened (before even any of the HTTP request is read):
Application["UploadState"] = "started";
...
////Following line thread blocks until entire request is read
// (even though I have only requested to read the first 10
// bytes of the incoming HTTP request stream (POSTed data).)
// Note this could be 30 minutes if the uploaded file is
// large and/or connection is slow. Also note that in ASP
// classic the same call will return immediately after the
// first 10 bytes are read (no thread block):
byte[] firstTenBytes = Request.BinaryRead(10);
////Following line executes only after entire HTTP request
// has been received (THAT'S A PROBLEM!):
Application["UploadState"] = "finished";
////This line would also thread block, if the BinaryRead
// line were commented out:
Stream request = Request.InputStream;
// Note I have not even called any methods on the
// InputStream - it seems the InputStream property
// itself is thread blocking.
////This line does NOT thread block...
Request.Filter = new MyFilterClass();
////...but MyFilterClass is never called by ASP.NET
// (the Read method in particular) until the entire
// request is read, thus the Filter class seems
// useless of my purposes.
} ...
In the ASP version, you stick Request.BinaryRead into a loop until you
read all the bytes. ASP classic blocks BinaryRead only until the bytes
specifed are read, so in your loop you can add a line like:
Application["BytesRead" & strUploadId] = iBytesRead
Then in a second browser window you can hit a page GetUploadStatus.asp
which would return the value of the Application variable. Please note
I have hand-coded the above, simplified example because the real code
is much more complicated and references a bunch of other classes which
would only serve as distractions and flamebait for all the
hypercritical newsreaders out there.
I also tried...
* The same code in an HttpHandler
* The same code in an XML Web Service
* The same code in various other event handlers (onload, oninit, etc.)
The problem seems to be in the HttpContext/HttpRequest classes thus no
matter where you stick the code, the thread blocking occurs.
I am trying for a 100% ASP.NET solution on the server side although if
somebody can send over some VB or C++ or whatever code that works or
even recommend another approach I'll consider you highly for
"Programming GOD" listing.
I posted this previously under the thread "Accessing
Request.InputStream / Request.BinaryRead *as the request is occuring*:
How???". Here's a few notes before you hit the reply key:
* HttpAsyncHandler appears to be used when the *response*, not the
request, is to be handled asynchronously, thus the class doesn't help.
* You cannot use Session to store the upload progress because pages
that use Session are serialized, thus the call to
GetUploadProgress.aspx in the second window would queue until the POST
acceptor main window finishes.
* The purpose is a rough estimate for an upload that would occur over
a long time (slow connection and/or very large file) thus latency
between byte sent from the client and byte received on the server and
when my thread is notified and finally round trip of the secondary
window to get the status should all be no problem. As long as the
client can see some sort of rough estimate that changes every few
seconds it's fine.
* I already searched extensively over several weeks and spent several
days trying to find a workaround and have failed. Although I am only a
humble staff programming, I am not a newbie - I have more than 6 years
experience with ASP, JSP, Java Servlets, ASP.NET, ATL C++ etc. and I'm
not often stumpted. **** Are you the programming GOD that can help me?
****
Thanks for your time.
Brian Birtle
Web Application Developer - VPD Group
International Technigroup Incorporated
http://www.iti-global.com/
http://birtle.com/
(The views above don't necessarily reflect ITI, blah blah blah...)