The UploadMgr library uploads files to the server, providing background uploads and progress feedback on modern browsers, falling back to traditional file upload on older browsers.
You can view the online demo at http://www.zenesis.com/UploadMgr/uploadmgr/demo/default/build/index.html
If you want to include the Upload Manager into your qooxdoo project, install it
with npx qx package install johnspackman/UploadMgr
To run the standalone demo, execute
git clone https://github.com/johnspackman/UploadMgr.git
cd UploadMgr
npm install --no-save --no-package-lock @qooxdoo/compiler
npx qx serve
then open http://localhost:8080 to start the demo application.
You need a UploadButton for the user to click and an UploadMgr to make the upload work:
var btn = new com.zenesis.qx.upload.UploadButton("Add File(s)", "myapp/test.png");
var uploader = new com.zenesis.qx.upload.UploadMgr(btn, "/demoupload");
var doc = this.getRoot();
doc.add(btn, { left: 50, top: 50 });
The constructor to UploadMgr takes two parameters – the first is the upload button that will open the browser’s “Open File” dialog, the second is the URL to upload to (ie the path that would normally be in a form element’s action attribute).
Every file that is to be uploaded is wrapped in an instance of
com.zenesis.qx.upload.File
, a normal Qooxdoo object that fires
events during the upload process; it has these properties:
The UploadMgr fires the “addFile” event when a new file has
been added to the upload queue and passes an instance of
com.zenesis.qx.upload.File
as the event’s data property.
Attach listeners to com.zenesis.qx.upload.File to track progress:
uploader.addListener("addFile", function(evt) {
var file = evt.getData();
var progressListenerId = file.addListener("changeProgress", function(evt) {
var file = evt.getTarget();
var uploadedSize = evt.getData();
this.debug("Upload " + file.getFilename() + ": " +
uploadedSize + " / " + file.getSize() + " - " +
Math.round(uploadedSize / file.getSize() * 100) + "%");
}, this);
// …snip… //
The "progress" property will give feedback about the quantity of data uploaded so far but is only available on browsers that support it (FF3+, Chrome, Safari, etc) so "changeProgress" may not fire; to cater for older browsers too, watch the “state” property:
// All browsers can at least get changes in state
var stateListenerId = file.addListener("changeState", function(evt) {
var state = evt.getData();
var file = evt.getTarget();
if (state == "uploading")
this.debug(file.getFilename() + " (Uploading...)");
else if (state == "uploaded")
this.debug(file.getFilename() + " (Complete)");
else if (state == "cancelled")
this.debug(file.getFilename() + " (Cancelled)");
// Remove the listeners
if (state == "uploaded" || state == "cancelled") {
file.removeListenerById(progressListenerId);
file.removeListenerById(stateListenerId);
}
}, this);
Changes to the “state” property are a good opportunity to remove the listeners on the file, too. Finally, the "response" property contains whatever was returned from the server. A more detailed example
Please see the Application.js for more detailed example.
You can have more than one upload button attached to an UploadMgr instance - this allows you to have one queue of files uploading and put "upload" buttons where it makes most sense for usability.
var secondBtn = new com.zenesis.qx.upload.UploadButton("Add File(s)",
"myapp/test.png");
uploader.addWidget(secondBtn);
You can remove them later if you wish:
// About to dispose of secondBtn - make uploader forget about it
uploader.removeWidget(secondBtn);
// ok to dispose
secondBtn.dispose();
To add parameters to the upload you can use UploadMgr.setParam(name, value)
to specify a name/value pair that will be sent with every upload.
uploader.setParam("MY_GLOBAL_PARAM", "some global value");
You can also set parameters on the widget that triggered the upload, and those parameters will only be sent for files uploaded via that widget. This is useful where you have multiple upload widgets in different places in your application and you want to associate different parameters for each.
btn.setParam("MY_WIDGET_PARAM", "which-widget-the-user-clicked");
Parameters set on the widget override global values set against the UploadMgr. You can override parameters on a per-file basis in the UploadMgr's addFile event handler, for example:
uploader.addListener("addFile", function(evt) {
var file = evt.getData();
file.setParam("MY_GLOBAL_PARAM", "a different value");
file.setParam("MY_FILE_PARAM", "some-value");
}
Note that in the example above, the file is given it's own value for MY_GLOBAL_PARAM - this overrides the previous global value, but only for this one file. File parameters take precedence over widget values, and file and widget values take precedence over global values. When overriding a global parameter value in this way, if you specify null as the value then the paramater will not be sent at all.
uploader.addListener("addFile", function(evt) {
var file = evt.getData();
// Do not send MY_GLOBAL_PARAM
file.setParam("MY_GLOBAL_PARAM", null);
}
The UploadMgr on the client sends files as “multipart/formdata”, ie the same as a