Re: Large File Uploads [was Re: Large volume file upload design question ]
Re: Large File Uploads [was Re: Large volume file upload design question ]
- Subject: Re: Large File Uploads [was Re: Large volume file upload design question ]
- From: Jonathan Rochkind <email@hidden>
- Date: Mon, 21 Jul 2003 12:33:37 -0500
At 05:53 PM 7/21/2003 +0100, Jonathan Fleming wrote:
Calling All Guru's
How can I... or can I even, link a long upload in with a LongRequestPage
(I've never used this feature, so ecuse me if it does not do what I am
thinking).
The basic problem here is that if you DON'T have concurrent request
handling turned on, you are going to run against that problem. Becuase,
since your app isn't handling multiple requests concurrently, the file
upload (comprimising one request) will block all other requests, whether
from that session or another session, until is complete. This is indeed
obviously a problem.
One solution, naturally, would be to turn concurrent request handling
on. Another, that I plan to work on when I get the chance, would be to
have your form be of a direct action type, rather than a component action
type, but use a custom request handling for handling the direct action-like
action. The custom request handler would be very much like the direct
action handler, but would NOT block, regardless of whether concurrent
request handling was enabled. It would effectively ignore the concurrent
request handling setting. Obviously, you'd need to be quite careful what
you do in this action, since the app might not be expecting concurrent
requests, but will get them to some degree.
Once you've solved this problem, you still have another problem, on the
browser end. If the form-submit is targetted to your ordinary main frame,
the BROWSER isn't going to want to display anything there (like a progress
bar, that you are trying to provide with WOLongResponse page!) until the
form submit is finished. You'd need to do something tricky with frames
and/or seperate browser windows to get the browser to display a progress
bar type thing while the form upload is in progress. [And this won't
neccesarily work with all browsers---it relies on the browser itself to be
multi-threaded, but I think all realistic browsers will perform properly].
I plan on getting this all together to work like this when I have time,
some time in the next month or two. It's definitely rather tricky, but I
think it's do-able.
1) First, if possible, I'd like to get the size of the file from the input
Stream before anything begins to get uploaded. How is it done or can't it
be done?
Well, you can't get it from the inputStream, but you can get it from the
WOMultipartIterator object. However, accessing the WOMultipartIterator
object is somewhat dangerous if you are using a component action, rather
than a direct action. [And using a direct action is a lot more work, but
do-able. See the example in the file upload examples in 5.2.] But see
currentRequest().multipartIterator().contentLengthRemaining(). Again, I
wouldn't try this in a component action.
Alternately, it may be possible to examine the WORequest headers directly
for the content-length header. Not sure if WO will give this to you this
way or not. But that's the header WOMultipartIterator is using anyhow.
In either case, this is just kind of an estimate, and will be dificult to
use effectively if you have more than one file in the form-submit, or some
huge amount of non-file data in the form-submit. It's dificult or
impossible to do anything about this, it's a HTTP issue, not a WO issue.
The info you want just ain't in the HTTP request in any way but this.
2) Armed with that info I'm hoping to tell the LongRequestReponse page to
kick in if the data is more than a particular length or simply attach it's
process to the length full stop.
Well, see the various caveats above about using the WOLongResponsePage with
an upload AT ALL. But with or without the WOLongResponse page, you can
certainly tell if the upload is Too Big. The problem then becomes... how do
I cancel the upload? It's tricky. An Apple Engineer told me that there is
no good way to get WO to close an incoming HTTP request connection before
it's fully complete. Which is what would be required here. However, there
may be various BAD ways which would work, if you catch the proper
exception. Not sure what will happen if you simply return from yoru
(direct) action method before you've fully read the InputStream. It won't
be pretty, but you may be able to get it to work. The problem is, not only
do you need to get WO to stop handling the request, you need to get the
BROWSER to realize that the server has closed the connection, and stop
trying to upload the gigantic file. But even harder than this, you'd need
to get the BROWSER to do more than display an error page "server has closed
connection", you want the browser to display a nice URL of your own
devising that's all pretty and explains what's going on.
It's going to be tricky.
middle of a process. Whereas doing a straight upload, if the user wants
out, they just press stop and that's exactly what happens everything
stops. I imagine your instance hangs as I have not yet tested in
deployment, but in development all functions of the browser hang and the
app has to be rebuilt to get it going again... worrying to say the least.
I need to overcome this problem badly. Who can help.
Well... if the user presses the "stop" button their browser, it should NOT
cause any particular problems for your WO application. It _will_ cause an
exception to be thrown from the takeValuesForRequest method (at least in a
component action---haven't investigated where/if the exception is thrown in
a direct action method). What type of exception? I'm not sure---it may
even depend on browser type. I've noticed the following exceptions thrown
from component takeValuesFromRequest, all of which MAY be caused by a
browser-stop button, I'm not sure.
1) An NSForwardException wrapping an IOException whose message is set to
"Error in file transfer."
2) A RuntimeException (base class, not an NSForwardException) whose message
is set to "Error writing to output stream: java.io.FileOutputStream."
Maybe a couple others too.
You _could_ catch this exception to be aware of this condition. But what
are the consequences of this exception being thrown, if you don't catch
it? Well, WO will instantiate a WOExceptionPage to report it, but the user
will never see it, because they've pressed the stop button, the browser is
no longer paying attention to anything the server may wish to return. So it
doens't really matter if you don't catch it.
3) Once finished I want to return to the upload form (how do you get the
stream to inform you that it has finished its processing so you can tell
the LongResponse page this?)
Not sure what you mean exactly, but I think my earlier comments outline
some of the dificulties with this sort of thing.
Good luck. It's a challenge. Like I said, I plan on attacking this myself
when I have time, and would be interested in any useful code you come up. I
will also share my code once I have time to deal with it.
--Jonathan
_______________________________________________
webobjects-dev mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/webobjects-dev
Do not post admin requests to the list. They will be ignored.