Google
 
欢迎光临
  发起投票 | 发起主题  
2001-04-12
男
搞定Mac OS,尝试写写iphone应用
帖子数: 14892
发帖数前10位(2)

 
http://www.asp.net/Forums/ShowPost.aspx?tabindex=1&PostID=55127
Author  Thread: HttpHandler or HttpModule for file upload, large files, progress indicator?
J B. Podolak is not online. Last active: 3/14/2004 4:52:17 PM J B. Podolak
bio.jpodolak.com
Joined: 22 Sep 2002
Total Posts: 6
 
HttpHandler or HttpModule for file upload, large files, progress indicator?
Posted: 22 Sep 2002 06:36 PM

I would like to use the built-in file upload handling features of ASP.NET, however I have found that even if you increase the maxRequestLength and executionTimeout values, after 180 seconds, the aspnet_wp is recycled because it thinks it is deadlocked.

In addition, there is the issue that there is no feedback to the client of whether the upload is proceeding or encountered an error (the globe just sits and spins).

What would be ideal would be to asynchronously intercept the incoming request in an HttpModule or HttpHandler, and since the content-length is first, be able to set some current bytes/total bytes value in the application. Then with the help of a little client-side javascript that opens a self-refreshing "progress indicator" modelessdialogbox that could read these values every few seconds, not only would the deadlock issue be solved, but the client would also get some visual indication that the upload is proceeding.

After scouring everything I could find in the way of documentation and newsgroups, I have not been able to locate any information on how to just "count the bytes" of a request as they come in, but it seems like the async StartBeginRequest event may be the key.

This sounds like a real common scenario, can anyone help me?

Thanks in advance!
J B. Podolak is not online. Last active: 3/14/2004 4:52:17 PM J B. Podolak
bio.jpodolak.com
Joined: 22 Sep 2002
Total Posts: 6
 
Somebody must know the answer, please help: HttpHandler or HttpModule for file upload, large files, progress indicator?
Posted: 27 Sep 2002 10:18 AM
Somebody in this forum most have dealt with this issue, and I could really use some advice. Perhaps my last post was not worded correctly, here's a simplification:

The built-in file upload handling features of ASP.NET load the entire request into server memory before you can save the file. If the file is large, this can cause execution timeouts, or at the very least, consume *huge* amounts of server memory. What I am looking for is a way to intercept an incoming request (asynchronously, I suppose) so that I can process the incoming bytes in smaller chucks, saving each chunk to the file as it is received, rather than waiting for the entire request to get loaded into server memory before processing. On the client side, I am using the standard <input type=file> tag, so the uploaded file(s) are sent in a multipart/form-encoded POST to the server.

Has anybody dealt with processing incoming request bodies as they arrive, rather than after the entire request is received?

Is there a way to use a custom HttpHandler to do this? Perhaps with the asynchronous BeginProcessRequest() function? Has anyone here done asynchronous processing?

Any help would be *greatly* appreciated!
damonz is not online. Last active: 5/5/2004 12:47:39 PM damonz
www.zirkler.com
Joined: 23 Jul 2002
Total Posts: 78
 
Re: Somebody must know the answer, please help: HttpHandler or HttpModule for file upload, large files, progress indicator?
Posted: 30 Sep 2002 04:27 PM
See:
http://www.asp.net/ControlGallery/ControlDetail.aspx?Control=222&tabindex=2

They've figured it out. This control is nice and should do all that you need to.

D
micklemj is not online. Last active: 10/12/2004 10:37:53 AM micklemj
Joined: 19 Aug 2002
Total Posts: 16
 
Re: Somebody must know the answer, please help: HttpHandler or HttpModule for file upload, large files, progress indicator?
Posted: 11 Nov 2002 11:59 AM
Did you ever resolve this problem?

We have been the same problem - we use modem access and occasionally upload files of around 2MB into a SQL2000 DB. Often this fails (not due to the internet connection), but due to some timeout or other.

We thought it may be the session timeout, but it happens before the session expires. I have also increased the scripttimeout and execution timeout properties without success....

If you have found a solution I would be very interested to hear about it.

James

J B. Podolak is not online. Last active: 3/14/2004 4:52:17 PM J B. Podolak
bio.jpodolak.com
Joined: 22 Sep 2002
Total Posts: 6
 
Re: Somebody must know the answer, please help: HttpHandler or HttpModule for file upload, large files, progress indicator?
Posted: 11 Nov 2002 10:08 PM
To micklemj:

Increasing the script timeout and execution timeout won't help,
it's the aspnet_wp.exe process that thinks it's deadlocked after
180 seconds and "recycles" itself for you (how nice of it!).

I have found a partial solution though. As long as ASP.NET is
serving some requests, aspnet_wp won't timeout. I have used
this solution for uploads that take up to an hour with success.
The way to make it work is to spawn a new window from the
page before starting the upload. The code in the spawned
page just refreshes itself every few seconds until the upload
is finished, then it closes itself.

However, this does not fix my main problem, which is that
the *entire* uploaded file is kept in server memory during
the upload. My uploads can be hundreds of megabytes, so
that is not feasible.

That's why I was asking about anyone who had worked with
asynchronous handlers... I thought maybe I could grab every
4000 bytes or so and dump it to a temp file, rather than wait
for the entire request to get there.

I know that there are 3rd party utilities for this, but that's not
an option for me, I have to write the code and no client-side
ActiveX controls are allowed (other than what comes with
Internet Explorer)

Hope this helps...
MarcHoeppner is not online. Last active: 7/10/2004 6:09:01 AM MarcHoeppner
www.neogeo.com
Joined: 16 Jun 2002
Total Posts: 91
 
Re: Somebody must know the answer, please help: HttpHandler or HttpModule for file upload, large files, progress indicator?
Posted: 12 Nov 2002 02:31 AM
I briefly researched that problem and I found two possible solutions (other than using ActiveX, Java or .NET DLLs on the client):

- open a second upload window (or use an IFRAME) that does the file POST. write a httphandler that handles the upload process on the server. in the while() loop for reading in the file from the stream, write the current number of received bytes into a static variable. use XMLHTTP or a simple page refresh every 5s or so in the first window to call back to the server. have the server read that static variable from the httphandler and return it to the client after the post-back.

- use ADO on the client to read in the file and upload it via an IFRAME. I forgot how that exactly worked, but you should be able to find a link on google if you look for 'file upload ADO object' or something similar.

hope this help!!

Marc

Marc Hoeppner
J B. Podolak is not online. Last active: 3/14/2004 4:52:17 PM J B. Podolak
bio.jpodolak.com
Joined: 22 Sep 2002
Total Posts: 6
 
Re: Somebody must know the answer, please help: HttpHandler or HttpModule for file upload, large files, progress indicator?
Posted: 12 Nov 2002 02:46 PM
To Marc Hoeppner:

Yes, as I mentioned in my previous post, I am using the "second window"
method to keep the upload alive (actually I use a modeless dialog box that
contains aframeset that contains an aspx page that contains client script that
refreshes every few seconds, but that's not my issue)

My issue is that the post from the main page uses the <input type=file>
control, so the *entire* file (or files) are sent in one big http request.
While this works, the aspx page receiving this huge post (which can be
hundreds of megabytes for my application) stores the *entire* request
in server memory before I get a chance to begin handling it.

Obviously, this will only marginally work with a single user, and if several
users try to upload simultaneously, the server will run out of memory.

What I need to do is intercept the request *AS IT COMES IN*, not after
it is complete.

That's why I was asking about asynchronous httprequest handlers.

Do you (or anyone else reading this) have any experience with these?

Can they be used to read an incoming request in chunks, so that the
server doesn't have to buffer the *entire* posted file in memory?

Any pointers greatly appreciated!

J B. Podolak
MarcHoeppner is not online. Last active: 7/10/2004 6:09:01 AM MarcHoeppner
www.neogeo.com
Joined: 16 Jun 2002
Total Posts: 91
 
Re: Somebody must know the answer, please help: HttpHandler or HttpModule for file upload, large files, progress indicator?
Posted: 12 Nov 2002 04:00 PM
>Do you (or anyone else reading this) have any experience with these?
>Can they be used to read an incoming request in chunks, so that the
>server doesn't have to buffer the *entire* posted file in memory?

Without having done exactly that as of yet, from my experience with HttpHandlers the answer is yes. You should be able to get the BeginRequest event and take over from there. The standard ASPX handler certainly does something similar for the native ASP.NET file upload. Anyway, it certainly is possible with an ISAPI filter/module, so that should work with either HttpModule or HttpHandler.

I took a quick look for you at my link list that I luckily still have from that research, so you may want to take a look at these links for an alternative ADO/XMLHTTP way of uploading files:

http://www.15seconds.com/issue/010522.htm
http://www.pstruh.cz/tips/detpg_uploadvbsie.htm

If you control the environment totally, you may want to think about a .NET DLL that is loaded via the object tag right inside the browser. You then can do anything like you would in an ordinary Windows Form application. The client needs .NET framework 1.1 installed in his machine, so this may be a show-stopper at the current time.

One last thought is to try something completly different: for a CMS-like application that we are currently writting, we have a similar problem with large files. Obviously the main problem with large files is the browser timeout that is hard to control. We are probably going to change the process totally, so that the user first gets fills out a form with all the meta data (name, description, author, keywords, categories, etc.) and then gets a ticket number from the system. He then mails the file to an email service on the same server. A windows service on the machine constantly checks for incoming email with a valid ticket number and then finishes the 'upload' process by adding both the meta data and the file to a database. The really nice thing about this is that the upload works asynchronously without the user having to wait in front of his browser or forcing him to deal with timeouts Smile

Hope this helps!

Best regards,

Marc




Marc Hoeppner
freakytard is not online. Last active: 10/14/2004 4:23:34 PM freakytard
www.freakytard.com
Joined: 22 Aug 2002
Total Posts: 39
 
Re: HttpHandler or HttpModule for file upload, large files, progress indicator?
Posted: 17 Nov 2002 09:43 PM
sounds interesting, anyone willing to post some sample code?
ups101 is not online. Last active: 6/29/2004 3:44:49 AM ups101
Joined: 04 Dec 2002
Total Posts: 54
 
Re: Somebody must know the answer, please help: HttpHandler or HttpModule for file upload, large files, progress indicator?
Posted: 04 Dec 2002 02:03 PM
Hi

I've been trying to crack this nut for the last 4 months. This is what I've got so far:

1. It can easily be done, if you set up a TcpListener, and direct the upload to a port other than 80. Via the TcpListener, you get the raw request stream, and you call all the shots yourself. No reading into server memory. I got this solution up and running. Tradeoff is, that not all networks are open to other ports than 80. Not all clients will be able to upload. So I took it down again... :-(

2. Studying the disassembly from abcupload.net, they only tap into the BeginRequest event via a HttpModule when implementing the progress bar. In other words: It is possible to split the http request somehow, without using either a HttpModule or HttpHandler. This must be first priority.

Turn this point around, and you get this:

They DO need to use a httpmodule to tap into the upload process when they implement the progress bar. That must mean, that their upload class does not fully split the upload, even though they do enable saving of the request in chunks of 8 kb. Otherwise, they would not have bothered with the HttpModule. I only make this point in the hope that it will point us in the right direction. I think it means, that a bufferedreader must be introduces somewhere...

Right now I am looking at the following two hopes:

1. The HttpContext.Request.Filter allows you to set a stream through which the request must pass. Maybe we can block the request in the filter...? Hmm...not counting on it though!

2. You can assign a new HttpApplication to a HttpContext, and set it to a class of your own. Remember, HttpApplication is the class "serving" HttpContext. I think this is the class that does the request reading. So if we could make our own implementation of this class, we could override the default reading method....somehow...hmm...sounds difficult!

3. Yes, async Http request handlers might also work. But don't they need to be registered in web.config? Based on the fact that abcupload.net does not need registration of handlers, I find it unlikely (Although they might create the async handler via a HttpHandlerFactory, thus not needing alterations in web.config.....hmm...is that possible?)

This problem MUST be solved, and abcupload.net shows that it can! We need a site dedicated to solving this problem. Or maybe a newsgroup. A place where we can meet and crack this nut. Anyone got any suggestions?

If anyone makes any progress concearning this problem, please email me at rh@hghardware.dk

Kind regards,
Rasmus
Denmark
Cyberfloatie is not online. Last active: 10/28/2004 12:13:21 AM Cyberfloatie
Joined: 13 Jul 2002
Total Posts: 21
 
Re: Somebody must know the answer, please help: HttpHandler or HttpModule for file upload, large files, progress indicator?
Posted: 05 Dec 2002 10:26 AM
I can provide a website for development and testing. I could even be talked into hosting a source control system of some type if there was enough interest.

Regards,

Doug Wilson
Fridge Productions

dw
J B. Podolak is not online. Last active: 3/14/2004 4:52:17 PM J B. Podolak
bio.jpodolak.com
Joined: 22 Sep 2002
Total Posts: 6
 
Re: Somebody must know the answer, please help: HttpHandler or HttpModule for file upload, large files, progress indicator?
Posted: 05 Dec 2002 11:24 AM
To Rasmus,

I looked into asynch httphandlers, but it would seem that these
are for when your custom processing needs to do asynch work.

ASP.NET just calls you once, then you call ASP.NET back when
you are done with your processing.

From what I have found in many, many web searches for docs,
the first thing that happens when a request (posted file) comes
in is that IIS mapping determines that it should go to the ASP.NET
dll, and then IIS "forwards" the request to whatever BeginRequest
handler is currently associated (built-in or your custom handler).

But, if I understand this process correctly, by the time BeginRequest
has been called, IIS has *already* received (and buffered) the
*entire* request in memory, so even though a custom BeginRequest
handler could read the request in, say, 8000 byte chunks and save
it to a temp file, the stream that it is reading is *already* completely
loaded into IIS memory, so it wouldn't help.

However, as you point out, AspUpload.Net claims that their GigUpload
technology keeps server memory load really low (from their docs, it
looks like the "chunksize" is all that is kept in memory).

So either they are only being *partially* truthful in their marketing
(ASP.NET only uses, say, 8k, but IIS uses the full file size), or I am
missing something.

I know that the interception of an incoming request "as it comes in"
can be done in an ISAPI extension or ISAPI filter, but everything
that I have read states that by the time *any* ASP.NET code sees
the request, IIS has already received the *entire* request.

Any Microsoft folks want to clarify this for me?

Given all that, I really don't know how AspUpload.Net does it without
using a client side control or a real (unmanaged) custom ISAPI filter.

There is one other way to make this work. If you can count on the
browser being Internet Explorer, you can use an ADO objects (the
XMLHttp and Stream objects) along with client-side javascript to
post the upload in small chunks. The problem with this is that the
security settings for Internet Explorer have to be relaxed to allow
reading of local files, and I'm pretty sure that most people won't
want to do this...

J B. Podolak
ltj2489 is not online. Last active: 12/9/2002 7:51:43 AM ltj2489
Joined: 02 Dec 2002
Total Posts: 1
 
Re: Somebody must know the answer, please help: HttpHandler or HttpModule for file upload, large files, progress indicator?
Posted: 05 Dec 2002 03:09 PM

I too am working on this problem for an application and here's my thoughts so far:

In the Application_BeginRequest event handler you do have control before the entire stream is buffered into memory. Just set a breakpoint in that method somewhere and you'll see that it fires immediately upon clicking your submit button. So that means that there is the ability to do some pre-processing on the request before the upload begins a-la ABC Upload. What the pre-processing is that we need to do is a mystery....

Here's what I have done:

I've trapped the request for the upload in Application_BeginRequest and cached it in the Cache object. I then launch a popup window which reads the cached Request object to try and access the Request.TotalBytes property to get the length of the input stream. The problem is that the input stream is so busy doing the upload that it never responds to the line of code trying to get the TotalBytes property. I know this because if I hit the Stop button on the main browser window (the one doing the upload) my popup immediately displays the amount of bytes uploaded to that point.

I feel so close, yet I think my approach may be too simplistic....

Jay
ups101 is not online. Last active: 6/29/2004 3:44:49 AM ups101
Joined: 04 Dec 2002
Total Posts: 54
 
Re: Somebody must know the answer, please help: HttpHandler or HttpModule for file upload, large files, progress indicator?
Posted: 05 Dec 2002 04:27 PM
To J B. Podolak and ITJ

Sounds like async handlers are out of the question. Too bad - they looked promising :-).

Regarding IIS buffering the request:
My experience is, that it is possible to intercept the event before the buffering occurs - as ITJ points out. However, as soon as a reference to the request stream is made, the *entire* request is read into memory, as J.B. points out.

I think we need to override the method supplying the request to HttpContext. I am not sure how to do this. However, one approach would be to implement your own hosting scenario. Look for System.Web.Hosting in the documentation, and it states, that you are able to host your own virtual address, thus CIRCUMVENTING IIS.

Basically it requires you to implement the SimpleWorkerRequest interface, which apparently will be responsible for serving the HttpContext object.

To me, this sounds like good news. However, I haven't been down that road yet, and are reluctant to go there, because it doesn't seem to be what abcupload.net is doing. However, after my exams (18/12), I'll probably try this.

I can only support your request for a microsoft developer to look at this. In my opinion, we need an optimal solution to this problem, as the current upload method clearly has shortcomings or even a memory leak, as indicated by the 4. post in this thread:

http://www.asp.net/Forums/ShowPost.aspx?tabindex=1&PostID=95255
ups101 is not online. Last active: 6/29/2004 3:44:49 AM ups101
Joined: 04 Dec 2002
Total Posts: 54
 
Re: Somebody must know the answer, please help: HttpHandler or HttpModule for file upload, large files, progress indicator?
Posted: 05 Dec 2002 07:24 PM
I've been doing some more digging in System.Web.Hosting assisted by the ms opensource Cassini web server documentation

I really believe we could get somewhere by giving this a shot. It is the backdoor into the top of the http request pipeline that we need.

When IIS receives a request for an aspx resource, it instantiates a HttpRuntime object, and calls ProcessRequest(HttpWorkerRequest hwr)

The HttpRuntime object is TOP of the http pipeline, as shown here:
http://msdn.microsoft.com/msdnmag/issues/02/09/HTTPPipelines/default.aspx

The hwr argument passed to the HttpRuntime object is the toolbox that we want to alter. Inside HttpWorkerRequest are all the methods that HttpRuntime uses when it wants the request processed. HttpWorkerRequest is an abstract class, so we can implement our own version, and override the methods responsible for reading the request.

There is even a class called SimpleWorkerRequest, which is already implementing HttpWorkerRequest. So in fact we only need to implement our own SimpleWorkerRequest.

By creating our own hosting environment, we do the job of IIS: We pass an instance of our SimpleWorkerRequest-derived class to HttpRuntime.ProcessRequest, to make it the new toolbox that HttpRuntime must use, when it wants the request processed.

How to setup a separate hosting environment? This articles explains how - and apparently, it seams quite possible:
http://www.iunknown.com/Weblog/HostingASP.NETinaWinForms.html

However, I find it slightly annoying that we have to go so far to theoretically have a chance of achieving the goal. I've found indications in MSDN about a possibility of changing the HttpWorkerRequest object, even without creating your own hosting environment, and I'll be looking at that next.

Hmm...once again my exam preparation was cancelled in favour of .net. Terrible. Only 4 days left. I'll be seeing you guys on the other side of the exams.
ups101 is not online. Last active: 6/29/2004 3:44:49 AM ups101
Joined: 04 Dec 2002
Total Posts: 54
 
Re: Somebody must know the answer, please help: HttpHandler or HttpModule for file upload, large files, progress indicator?
Posted: 12 Dec 2002 04:48 PM
Please, could some asp.net team people comment on these ideas? This nut is not nearly cracked, and I really could use a pointer in the right direction.

Kind regards,
Rasmus
Cyberfloatie is not online. Last active: 10/28/2004 12:13:21 AM Cyberfloatie
Joined: 13 Jul 2002
Total Posts: 21
 
Re: Somebody must know the answer, please help: HttpHandler or HttpModule for file upload, large files, progress indicator?
Posted: 13 Dec 2002 09:37 AM
UPS,

I'm working on this problem as well. Like you, I have too many demands on my time, but rest assured, I will post here as I make progress.

dw
ups101 is not online. Last active: 6/29/2004 3:44:49 AM ups101
Joined: 04 Dec 2002
Total Posts: 54
 
Re: HttpHandler or HttpModule for file upload, large files, progress indicator?
Posted: 13 Dec 2002 05:30 PM
We'll get this together! :-)

I am now more certain that I am onto the right track:

First of all, don't bother setting up your own hosting environment just to get to HttpWorkerRequest. As I indicated in my last post, it really is quite possible to get the HttpWorkerRequest directly from the current request, though I'm still working on how :-).

This is the plan:

1. Intercept request with a HttpModule, setup the BeginRequest event handler
2. In the BeginRequest event, get access to the HttpWorkerRequest object - somehow :-(
3. Call the appropriate methods of hwr object, such as ReadEntityBody(byte[] buffer, int size) in a while loop with an appropriate sized buffer, and store the request chunks somewhere (not in memory) between loops, untill full request has been read.
4. Extract just the file data from the saved request.
5. Somehow indicate to the rest of the processing pipeline, that the request has already been read, so no more calls to ReadEntityBody and methods alike are made. (yes, very abstract :-)).

The reason why I am more sure now, is after a conversation with abcupload.net support, and some more testing. It seems that abcupload.net is NOT able to do its division of the upload without a httpmodule! I know I've indicated something to the contrary earlier - however, I've also speculated that something was wrong about them only using the httpmodule for progress indication. Generally, I believe I had misunderstood the functionality of abcupload.net...sorry about that :-)

However, with help from the support team, it has now become clear, that abcupload.net DOES rely on a httpmodule for BOTH gigupload technology and progress indication! So that opens up for the intuitively approach stated above, and gives some assurance of this being a possible solution.

Still quite a few puzzles are left unsolved. So once again: asp.net team people, please tell how I can get the HttpWorkerRequest from HttpApplication? - I know it must be possible somehow. This is really the most essential need.

Regards,
Rasmus
J B. Podolak is not online. Last active: 3/14/2004 4:52:17 PM J B. Podolak
bio.jpodolak.com
Joined: 22 Sep 2002
Total Posts: 6
 
Re: HttpHandler or HttpModule for file upload, large files, progress indicator?
Posted: 16 Dec 2002 02:34 PM
Rasmus (ups101):

Here's how to get at the HttpWorkerRequest from within a
BeginRequest handler (I found it in another thread):

private void OnBeginRequest(object src, EventArgs e)
{
HttpApplication app = (HttpApplication)src;
HttpWorkerRequest workerRequest = (HttpWorkerRequest)app.Context.GetType()
.GetProperty("WorkerRequest", (BindingFlags)36)
.GetValue(app.Context, null);
}

Also of interest, here's what I found on "ending a request" in
an HttpModule:

The HttpApplication object exposes the CompleteRequest method.
If an HTTP module's event handler calls HttpApplication.CompleteRequest,
normal pipeline processing is interrupted after the current event
completes (including the processing of any other registered event handlers).
A module that terminates the normal processing of a message is expected
to generate an appropriate HTTP response message.

Given the above, along with ReadEntityBody() maybe we can make this
work correctly...

Please post your results!

J B. Podolak
ups101 is not online. Last active: 6/29/2004 3:44:49 AM ups101
Joined: 04 Dec 2002
Total Posts: 54
 
Re: HttpHandler or HttpModule for file upload, large files, progress indicator?
Posted: 16 Dec 2002 05:17 PM
J.B. Podolak

Beautiful! I think you're right; this should be possible now.

I'll post results in a few days...just one more exam to go wednesday.


BTW:
I believe (BindingFlags)36 can be replaced by BindingFlags.NonPublic | BindingFlags.Instance

IL looks the same...

Kind regards,
Rasmus
CodeRage is not online. Last active: 1/7/2003 6:49:16 PM CodeRage
Joined: 12 Dec 2002
Total Posts: 6
 
Re: HttpHandler or HttpModule for file upload, large files, progress indicator?
Posted: 18 Dec 2002 11:55 PM
Ok, I have some very preliminary results from experimenting with the ideas presented above.

I build an HttpModule to process the upload in chunks successfully. I used a 64K buffer. It made a huge difference vesus using the .NET classes to pull in the file. No more loading the entire file's content in memory!!! But, that leaves more work for us....

If you have an incoming http request and you capture it using the BeginRequest event in the ASP.NET pipeline and you access the HttpRequest object (from the Context object) in any way, ASP.NET will load the entire request's content, regardless if it is a multipart request or not, into memory. I experimented with various ways before attempting to use the HttpWorkerRequest class.

Bottom line, if you access even one property of the HttpRequest object, you're getting everything all at once.

Ok, so using the methods presented above, I was able to easily snag the httpWorkerRequest interface and exploit it.

Indeed you have to use the ReadEntityBody method, but not exactly in the way you might think. When a multipart HTTP request comes in, the first pice of the request is "preloaded." The ReadEntutyBody method is only good for the portion of the request that is NOT preloaded. Therefore every HTTP request that comes in has some or all of its content preloaded. So you use the GetPreloadedEntityBody method to snag the preloaded portion of the request. The you use the IsEntireEntityBodyIsPreloaded method to check if you have the entire request or not. If not, then you can use the ReadEntityBody method to finish reading the request. FYI - the preloaded portion of the request is always 49152 bytes on my system.

So you chunk-in the rest of the request writing the chunk to disk and get th desired solution to the original problem presented in this thread. But.....there's always a BUT!

We're now talking about a raw HTTP request. (As if you didn't see that coming...)
So now we need a reliable method of parsing the request as it comes in such that we are able to detect that an HTTP frame contains a file and we are only writing that file's contents to disk. All in all, it shouldn't be too bad. I don't have time tonight to write a parser! I have real work to do, but this thread was very interesting!

I wrote my code in VB.NET (sorry, C# dudes). Luckily, I code in the framework, not like a typical VB programmer. So I'll place the code in the next reply.

CodeRage!




CodeRage is not online. Last active: 1/7/2003 6:49:16 PM CodeRage
Joined: 12 Dec 2002
Total Posts: 6
 
Re: HttpHandler or HttpModule for file upload, large files, progress indicator?
Posted: 19 Dec 2002 12:07 AM
Ok, here's the html file tha has the form:

<html>
<head><title>UploadForm</title></head>
<body>
<form name="UploadForm" method="post" encoding="multipart/form-data">
File to Upload:&nbsp;<input type="file" name="file"><br><br>
<input type="submit" value="Submit">
</form>
</body>
</html>





Ok, now add the following to your Web.config file inside the <system.web> element:

<httpRuntime executionTimeout="1800" maxRequestLength="524288000" />

<httpModules>
<add name="UploadModule" type="HttpUploadApp.UploadModule,HttpUploadApp" />
</httpModules>


This configures the timeout to 30 minutes, accepts up to 500MB files, and registers the HttpModule. My assembly name is HttpUploadApp as the namespace is the same thing.





Next is the HttpModule class. This is a rough example that writes every HTTP request that has a content body to a file whose name is a GUID with a ".txt" extension saved in a directory named "C:\Upload\". This was just for test purposes!!!
HttpModule class (VB.NET):

Imports System
Imports System.IO
Imports System.Web


Public Class UploadModule

Implements IHttpModule

Public Sub New()
MyBase.New()
End Sub

Public Sub Dispose() Implements System.Web.IHttpModule.Dispose
End Sub

Public Sub Init(ByVal context As System.Web.HttpApplication) Implements System.Web.IHttpModule.Init
AddHandler context.BeginRequest, AddressOf BeginRequest
End Sub

Private Sub BeginRequest(ByVal source As Object, ByVal e As EventArgs)

Dim app As HttpApplication = CType(source, HttpApplication)
Dim context As HttpContext = app.Context

' Get the HttpWorkerRequest Object!!!
Dim hwr As HttpWorkerRequest = CType(context.GetType.GetProperty("WorkerRequest", Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic).GetValue(context, Nothing), HttpWorkerRequest)

If hwr.HasEntityBody Then

Dim g As Guid = Guid.NewGuid()
Dim fn As String = "C:\Upload\" + g.ToString + ".txt"

Dim fs As New FileStream(fn, FileMode.CreateNew, FileAccess.Write, FileShare.Read)
Try

Const BUFFSIZE As Integer = 65536

Dim Buffer As Byte()
Dim Received As Integer = 0
Dim TotalReceived As Integer = 0
Dim ContentLength As Integer = CType(hwr.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentLength), Integer)

Buffer = hwr.GetPreloadedEntityBody()
fs.Write(Buffer, 0, Buffer.Length)
Received = Buffer.Length
TotalReceived += Received

If Not hwr.IsEntireEntityBodyIsPreloaded Then

While (ContentLength - TotalReceived) >= Received
Buffer = New Byte(BUFFSIZE) {}
Received = hwr.ReadEntityBody(Buffer, BUFFSIZE)
fs.Write(Buffer, 0, Received)
TotalReceived += Received
End While

Received = hwr.ReadEntityBody(Buffer, (ContentLength - TotalReceived))
fs.Write(Buffer, 0, Received)
TotalReceived += Received

End If

fs.Flush()

Catch ex As Exception

Finally
fs.Close()
End Try

context.Response.Redirect("UploadForm.aspx")


End If

End Sub

End Class





Ok, that's it. What I didn't address here was keeping th aspnet_wp.exe process from recyling itself by opening another client-side browser winfow that loads an .aspx page with a client-side (JavaScript) timer refreshing itself every 10 seconds or so. Anyone can write that code --- it's so simple!!!


CodeRage!



ups101 is not online. Last active: 6/29/2004 3:44:49 AM ups101
Joined: 04 Dec 2002
Total Posts: 54
 
Re: HttpHandler or HttpModule for file upload, large files, progress indicator?
Posted: 19 Dec 2002 04:56 AM
YAHOO!

This is just wonderful CodeRage!
Your solution to redirect after upload is perfect! That solves the problem of signalling the rest of the pipeline.

Yes, the http must be parsed. But as you point out, this is no big deal compared to what we've got not.

WOW! Was that nice or what? We're now able to do REAL uploading, and besides from the abcupload.net team, this must be valuable information to a lot of people!

For me, exams are now over, THIS NUT HAS BEEN CRACKED, and the weather is not too cold...this has really made my day, and many to come :-)

Kind Regards,
Rasmus




Cyberfloatie is not online. Last active: 10/28/2004 12:13:21 AM Cyberfloatie
Joined: 13 Jul 2002
Total Posts: 21
 
Re: HttpHandler or HttpModule for file upload, large files, progress indicator?
Posted: 20 Dec 2002 12:49 AM
I did everything you said but every time I post I get the following error:

Maximum request length exceeded.
Exception Details: System.Web.HttpException: Maximum request length exceeded.
Stack Trace:
[HttpException (0x80004005): Maximum request length exceeded.]
System.Web.HttpRequest.GetEntireRawContent() +891
System.Web.HttpRequest.FillInFormCollection() +129
System.Web.HttpRequest.get_Form() +50
System.Web.TraceContext.InitRequest() +703
System.Web.TraceContext.VerifyStart() +160
System.Web.HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +216
System.Web.HttpRuntime.ProcessRequestInternal(HttpWorkerRequest wr) +479

I even modified the httpRuntime key in machine.config to have the value 524288000 and still get the same result.

dw
Bjorn.B is not online. Last active: 2/5/2003 8:05:10 AM Bjorn.B
www.send2store.com
Joined: 20 Dec 2002
Total Posts: 2
 
Re: HttpHandler or HttpModule for file upload, large files, progress indicator?
Posted: 20 Dec 2002 04:27 AM
Ok, boys

I found your posts last week and started working on your problem.
I hereby post you my C# code, since the code above is written in some
sort of VB.net code Smile

I'm working on the rest of the story now to pipe everything from the request
to the iis but after I cut out the file from the request. In order not to do any
redirection anymore.

I hope you find this usefull :

using System;
using System.Web;
using System.IO;
using System.Reflection;

namespace My.PlayGround
{
/// <summary>
/// Summary description for UploadHandler.
/// </summary>
public class UploadHandler : IHttpModule
{
public UploadHandler()
{
}

public void Init(HttpApplication application)
{
// Register our event handler with with the application object
application.BeginRequest += new EventHandler(this.BeginRequest);
}

public void Dispose()
{}

public void BeginRequest(object sender, EventArgs args)
{
try
{
// Create an instance of th application object
HttpApplication application = (HttpApplication) sender;
// Create an instance of the HTTP worker request
HttpWorkerRequest request = (HttpWorkerRequest) application.Context.GetType().GetProperty("WorkerRequest", (BindingFlags)36).GetValue(application.Context, null);

// Only trigger if the request is of type 'multipart/form-data'
if(application.Context.Request.ContentType.IndexOf("multipart/form-data") > -1)
{
// Create a new unique identifier to identify each request
string guid = Guid.NewGuid().ToString();
// Please alter pathname because the root of the C drive is not really the place to put your tempfiles
string filename = "c:\\requests\\request_" + guid + ".txt";

// Check if a request body is sent by the browser
if(request.HasEntityBody())
{
// Get the content length of the request
int content_length = Convert.ToInt32(request.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentLength));
int content_received = 0;
// This is a nice feature to redirect users if they upload a file
// larger then 100Mb BEFORE it is being uploaded
if(content_length > 102400000)
{
application.Context.Response.Redirect("http://www.av.com");
}

// Create a file to store the stream
FileStream newFile = new FileStream(filename, FileMode.Create);

// Get the preloaded buffered data
byte[] body = request.GetPreloadedEntityBody();
content_received += body.Length;

// Write the preloaded data to new file
newFile.Write(body, 0, body.Length);

// Get all the other data to be written to file if available
if(!request.IsEntireEntityBodyIsPreloaded())
{
// Create an input buffer to store the incomming data
byte[] a_buffer = new byte[16384];
int bytes_read = 16384;

while((content_length - content_received) >= bytes_read)
{
bytes_read = request.ReadEntityBody(a_buffer, a_buffer.Length);
content_received += bytes_read;
newFile.Write(a_buffer, 0, bytes_read);
}

// Read the last part of the stream
bytes_read = request.ReadEntityBody(a_buffer, (content_length - content_received));
newFile.Write(a_buffer, 0, bytes_read);
content_received += bytes_read;
}

// Flush all data to the file
newFile.Flush();

// Close the file
newFile.Close();

// Redirect to the page to avoid the browser hanging
string current_page = application.Context.Request.CurrentExecutionFilePath;
current_page = current_page.Substring(current_page.LastIndexOf("/")+1) + "?" + application.Context.Request.QueryString;
application.Context.Response.Redirect(current_page);
}
}
}
catch(System.Threading.ThreadAbortException)
{}
catch(Exception exception)
{
object e = exception;
}
}
}
}

儿子说:我是黑猫警长,当然要有胡子了!

2004-10-29 14:44 第 1 楼 回复 | 引用 | 编辑 | | Top

  1. 主页
  2. »
  3. 论坛首页
  4. »
  5. 科技文化
  6. »
  7. IT技术
  8. »
  9. HttpHandler or HttpModule for file upload, large files, progress indicator?
 

同主题阅读




Powered By Openlab v3.0 (Debug Build: 1.24389) © 2010. 页面执行: 0.016秒. 内存使用: 477.3MB. 5 次数据库查询.

京ICP备05050892号