3

I'm looking for a way to do file uploads, with a custom progress bar, with google web toolkit. Not looking for a plugin which shows its own progress bar, I'm rather looking for something which will call my callback method and notify it of progress, so I can show my own progress bar.

If that's not possible, then I'd like to know how to access the HTML5 File API so I can build my own file uploader widget.

Any ideas?

Thanks.

Manolo Carrasco Moñino
  • 9,723
  • 1
  • 22
  • 27
Ali
  • 261,656
  • 265
  • 575
  • 769

2 Answers2

5

There are many issues in GWT which makes difficult deal with this:

  • There is no FormData object in GWT, so you have to use JSNI to get one.
  • RequestBuilder does not support sending FormaData but only strings.
  • RequestBuilder does not support upload or download progress notifications.
  • FileUpload does not support the multiple attribute.
  • The Elemental package in GWT only works with webkit browsers, and I had some issues last time I tried to use the File Api.

Fortunately, gwtquery 1.0.0 has a bunch of features which facilitates to solve the problem.

Here you have a working example (with very few lines of code), which works in all browsers supporting the HTML5 file api:

import static com.google.gwt.query.client.GQuery.*;
[...]

final FileUpload fileUpload = new FileUpload();
RootPanel.get().add(fileUpload);

$(fileUpload)
  // FileUpload does not have a way to set the multiple attribute,
  // we use gQuery instead
  .prop("multiple", true)
  // We use gQuery events mechanism
  .on("change", new Function() {
    public void f() {
      // Use gQuery utils to create a FormData object instead of JSNI
      JavaScriptObject form = JsUtils.runJavascriptFunction(window, "eval", "new FormData()");
      // Get an array with the files selected
      JsArray<JavaScriptObject> files =  $(fileUpload).prop("files");
      // Add each file to the FormData
      for (int i = 0, l = files.length(); i < l; i++) {
        JsUtils.runJavascriptFunction(form, "append", "file-" + i, files.get(i));
      }

      // Use gQuery ajax instead of RequestBuilder because it 
      // supports FormData and progress
      Ajax.ajax(Ajax.createSettings()
                    .setUrl(url)
                    .setData((Properties)form))
        // gQuery ajax returns a promise, making the code more declarative
        .progress(new Function() {
          public void f() {
            double total = arguments(0);
            double done = arguments(1);
            double percent = arguments(2);
            // Here you can update your progress bar
            console.log("Uploaded " + done + "/" + total + " (" + percent + "%)");
          }
        })
        .done(new Function() {
          public void f() {
            console.log("Files uploaded, server response is: " + arguments(0));
          }
        })
        .fail(new Function() {
          public void f() {
            console.log("Something went wrong: " + arguments(0));
          }
        });
    }
});

Another option is to use gwtupload, which supports any browser, and it comes with some nice widgets and progress bar, even you can plug your own progress and status widgets.

It does not use HTML5 File api yet but an ajax solution based on a server listener. It will though, support html5 in future versions, falling back to ajax mechanism for old browsers. When gwtupload supports this, you wont have to modify anything in your code.

Manolo Carrasco Moñino
  • 9,723
  • 1
  • 22
  • 27
0

All the building blocks are in Elemental but might not work everywhere (Elemental is "close to the metal", without any support detection or hiding/working around browser bugs/discrepancies).

Or you can use JSNI.

Thomas Broyer
  • 64,353
  • 7
  • 91
  • 164
  • I can't find a link to the javadocs of elemantal, or anywhere with more code examples.. – Ali Jan 13 '14 at 11:56
  • We don't generate the javadoc for Elemental. There's an example in the [GWT repo](https://gwt.googlesource.com/gwt/+/master/elemental/examples/), but not about the File API. That said, you don't really need docs: Elemental is a quasi-direct mapping of the JS APIs. – Thomas Broyer Jan 13 '14 at 12:00
  • You can't really expect people to know how to use it without some javadocs or at least some documentation of which classes/methods are available.. – Ali Jan 13 '14 at 20:21
  • I said we don't generate the javadoc, this is the current situation; I didn't say that was a conscious decision. For the time being, you'd have to use your IDE to explore the classes. Also note that Elemental is still in "experimental" state (this should hopefully change in GWT 3.0 later this year). That said, I think the examples at least give you the "entry point" classes from where you can explore further (and don't forget that it's supposed to just map to the JS APIs) – Thomas Broyer Jan 14 '14 at 09:14
  • is it included in the normal gwt download, or does it have to be downloaded separately? P.S, thanks for the help. – Ali Jan 14 '14 at 14:43
  • 1
    The JAR is in the [GWT SDK](http://www.gwtproject.org/download.html) and in [Central](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.google.gwt%22%20AND%20a%3A%22gwt-elemental%22) – Thomas Broyer Jan 14 '14 at 15:19