« Return to Thread: File upload progress
2009/6/7 Mike Wilson <mikewse@...>
Lance wrote:dwr.engine.cancelUpload("myUpload");</javascript>engine.js generates an invocationId which is passed to the server which can be used to cancel an upload or poll it's current progress.2) Generic progress and cancellationAs you mentioned in an earlier mail, it could be interesting to provide a generic progress/cancellation mechanism for all calls, not just for file uploads. I then think it would be natural to return an object from any async call following the Deferred/Future pattern. This object could be used for asking about progress, completion status or to trigger cancellation, and would replace (but possibly contain) the invocationId in your example.If providing progress for all kinds of requests, then we can not depend on always getting a percentage to the progress callback, as we typically don't know the size of outbound data. The parameters could instead be designed this way:function(transferredBytes, totalBytes)and the totalBytes would only be set in the cases when we do have that information (and could easily be converted to a percentage). When totalBytes is undefined, a progress dialog could still show the running transferredBytes count.Hmm... this locks us into a file upload now rather than a more generic process percentage. I'm not 100% on this but could be talked into it.
3) Invocation idAfter thinking a fair bit on this I'm a little worried about us taking the responsibility to create a unique id in client code. Joe had the same dilemma for the script session ids and decided to go with server-side generation. Also, we already have the scriptSessionId that is such a unique number that identifies a loaded page in the browser.The invocationId needs to uniquely identify each call to the server and basing off the scriptSessionId we would just have to add a sequential call index number that we can keep locally in the client layer.What I just recommended doesn't work if we disable script sessions, and this is a configuration I am personally interested in. Though, if disabling script sessions I think it is ok to require the user code to invent a good enough invocationId. So, by default I think we should use the scriptSessionId algorithm, and then allow it to be overridden in the options object.
I should mention that we already have this sequential number as well; the batch id. So, the combination of scriptSessionId and batchId uniquely identifies every call to the server, including file uploads.My original invocationId used scriptSessionId + batchId but I moved to a random number to support a DWR mode without script sessions.
Perhaps I could check if scriptSessionId is null and only use the random number in this case.
Remote.uploadFile(dwr.util.byId("myFile"), {
callback: ...,
progressCallback: ...});Here the default ScriptSession-based incovationId is used, so the client layer needs to know the scriptSessionId before sending along the upload, as we would otherwise not know what invocationId to poll progress about.Thus, if scriptSessionId has not yet been set we need to send a pre-flight call that retrieves this id (this is always done by the first call from a fresh page, f ex by reverse Ajax polls when using that mode). After the return of that request we can then start the real upload request.
Remote.uploadFile(dwr.util.byId("myFile"), {
callback: ...,
progressCallback: ...,invocationId: ...});Here a custom incovationId is used, so we already know what invocationId to poll for in the progress handling. No scriptSessionId or pre-flight call needed.
Summing these suggestions up, this is how I would expect them to work:Specifying no progress callback means no progress handling will be done. The returned Deferred object allows us to manually check progress or cancel upload:var deferredInvocation = Remote.uploadFile(
dwr.util.byId("myFile"),{
callback: ...}
);dwr.engine.getProgress(deferredInvocation) // sends progress check requestdwr.engine.isCompleted(deferredInvocation) // internal flag, no request neededdwr.engine.cancel(deferredInvocation)[Some more thought could be put into these method names]Specifying a progress callback means progress handling will be active (in this case with scriptSessionId algorithm):var deferredInvocation = Remote.uploadFile(
dwr.util.byId("myFile"),{
callback: ...,
progressCallback: function(...) {},progressInterval: 500 // msec}
);And finally, also specifying an invocationId means that we override the scriptSessionId algorithm with our own:var deferredInvocation = Remote.uploadFile(
dwr.util.byId("myFile"),{
callback: ...,
progressCallback: function(...) {},progressInterval: 500, // msecinvocationId: "my Internet-wide unique string"}
);This works for me... I originally considered returning an object from a DWR call but wasn't sold on the idea since in sync mode {async: false} DWR returns the remote response. I wasn't sure of the implications here. This will obviously require a bit more work to implement this approach.
If the scriptSessionId suggestion above works out, then I guess the default upload manager should store progress on the script session.It's trivial to plug in a ScriptSessionUploadManager
Another (default) stores to a local map.I'm not sure what you mean with "local map"?I just mean a member variable on the DefaultUploadManager singleton
I remember from a previous discussion that it was suggested that progress could be delivered by Reverse Ajax, if active on the page. I'm not sure how much that would complicate things.I think that reverse ajax polls are less frequent than what is required to update a progress widget. The two could be combined in the future but I'm not going to attempt this at this stage.
« Return to Thread: File upload progress
| Free embeddable forum powered by Nabble | Forum Help |