Instead of using window you should almost always use $wnd . Learn more about JSNI at https://developers.google.com/web-toolkit/doc/latest/DevGuideCodingBasicsJSNI#writing .
It may also be useful to add a debugger statement when using something like Firebug or Chrome Inspector. This statement will stop the JS code in the debugger, as if you set a breakpoint there, you can debug Javascript by going one line at a time to see exactly what went wrong.
And finally, are you sure that the file you are reading is resolved by the browser? From http://dev.w3.org/2006/webapi/FileAPI/#dfn-SecurityError, this error can occur because the browser is not allowed to access the file. Instead of passing to String, you can go to the <input type='file' /> with which the user interacts, and get the file that they selected from there.
Update (sorry for the delay, apparently the previous update I did was thrown away, it took a bit to rewrite it):
A couple of erroneous assumptions are made in the source code. Most of my reading is http://www.html5rocks.com/en/tutorials/file/dndfiles/ , plus a bit of experimentation.
- Firstly, you can get the real path from the
<input type='file' /> field in combination with - that you can read arbitrary files from the user's file system along the way and finally
- that the
FileReader API is synchronous.
For security reasons, most browsers do not give real paths when reading the file name - check the line you get from upload.getFilename() in several browsers to see what it gives is not enough to download the file. The second problem is also security - it can be of little use to be able to read from the file system, simply using a line to specify the file to read.
For these first two reasons, you need to specify input for the files it is working on. Browsers that support the FileReader API allow you to access this by reading the files property of the input element. Two easy ways to get this is to work with NativeElement.getEventTarget () in jsni or just work with FileUpload.getElement (). Keep in mind that this files property contains several elements by default, so in this case, like yours, just read the null element.
private native void loadContents(NativeEvent evt) /*-{ if ($wnd.File && $wnd.FileReader && $wnd.FileList && $wnd.Blob) { // Great success! All the File APIs are supported. var reader = new FileReader(); reader.readAsText(evt.target.files[0]); //...
or
private native void loadContents(Element elt) /*-{ if ($wnd.File && $wnd.FileReader && $wnd.FileList && $wnd.Blob) { // Great success! All the File APIs are supported. var reader = new FileReader(); reader.readAsText(elt.files[0]); //...
In the last fragment, the FileReader api is asynchronous - you do not get the full contents of the file immediately, but you need to wait until the onloadend callback is called (again, from http://www.html5rocks.com/en/tutorials/file/dndfiles/ ) These files may be large enough so that you do not want the application to lock while reading, so the specification seems to assume this as the default value.
That's why I ended up creating new void loadContents methods instead of storing the code in the onClick method - this method is called when the ChangeEvent field is ChangeEvent off to start reading in the file, although it could be written in another way.
// fields to hold current state private String fileName; private String contents; public void setContents(String contents) { this.contents = contents; } // helper method to read contents asynchronously private native void loadContents(NativeEvent evt) /*-{; if ($wnd.File && $wnd.FileReader && $wnd.FileList && $wnd.Blob) { var that = this; // Great success! All the File APIs are supported. var reader = new FileReader(); reader.readAsText(evt.target.files[0]); reader.onloadend = function(event) { that.@com.sencha.gxt.examples.test.client.Test ::setContents(Ljava/lang/String;)(event.target.result); }; } else { $wnd.alert('The File APIs are not fully supported in this browser.'); } }-*/; // original createUploadBox private DialogBox createUploadBox() { final DialogBox uploadBox = new DialogBox(); VerticalPanel vpanel = new VerticalPanel(); String title = "Select a .gms file to open:"; final FileUpload upload = new FileUpload(); upload.addChangeHandler(new ChangeHandler() { @Override public void onChange(ChangeEvent event) { loadContents(event.getNativeEvent()); fileName = upload.getFilename(); } }); // continue setup
Then the "Ok" button is read from the fields. It would probably be wise to check that the content is not null in ClickHandler , and maybe even set it to zero when FileUpload ChangeEvent turned off.