- From: Michael A. Puls II <shadow2531@gmail.com>
- Date: Mon, 17 Aug 2009 22:37:42 -0400
- To: public-webapps <public-webapps@w3.org>
I think it'd be great to have a *simple to use* API specifically for loading local files on local pages (file://). There's already DOM3 Load and Save, but few want anything to do with that (it's not simple for one). There's also the previous document.load, but it's half broken in Opera, not implemented in Safari (unless things have changed recently) and isn't very good with error handling in Firefox. In other words, it's a mess. There's also XHR, but it doesn't really support file://. Firefox, Safari and Opera have implemented file:// access, but they don't all use the same security restrictions, don't all handle errors the same and don't simulate HTTP status codes for local file operations. This makes loading a local file a mess with XHR and makes it so you have to use different conditions in the readystatechange callback compared to HTTP. It's possible though to load a local file, but it's impossible to differentiate between the different type of errors (like file not found, access denied, read error, cross-origin attempt etc.). IE doesn't support accessing file:// with XHR, so can't comment on it. With that said, here's an idea (and what I'd like): There should be a FileReader interface that supports just load(fileURI) and error and load events (via onerror/onload or through addEventListener). Then, there'd be different types of reader objects that inherit from FileReader. The two that I'm suggesting are TextFileReader and BinaryFileReader. (I believe it's better to separate functionality into 2 separate objects instead of mixing things.) They would work like this: var treader = new TextFileReader(); treader.addEventListener("load", function(e) { alert(e.text); }, false); treader.addEventListener("error", function(e) { alert(e.error.code); }, false); and var breader = new BinaryFileReader(); breader.addEventListener("load", function(e) { alert(e.bytes); }, false); breader.addEventListener("error", function(e) { alert(e.error.code); }, false); 'load' does not fire if there's an error. 'error' fires for the first error (the code would return after the first error). Nothing throws an exception. The author can do that in the error handler if desired. That way, you can do things how you want. You can also easily wrap things to use callback functions instead if you really wanted. For the load event objects, there'd be a BinaryReaderLoadEvent that has a bytes getter and a TextReaderLoadEvent that has a text getter. They would inherit from Event. (I like these separate instead of having one event object that has both .text and .bytes where one might be null or something) For the error event object, there'd be a FileReaderErrorEvent object that has an error getter that returns a FileReaderException object, which inherits from DOMException and has a code getter that returns different error codes for file not found etc. (that would have to be agreed upon). It'd all look something like this (don't know idl stuff very well, but it should be good enough to get the idea across) interface FileReader { onload onerror addEventListener void load(uri); }; interface TestFileReader : FileReader { }; interface BinaryFileReader : FileReader { }; interface TextFileReaderLoadEvent : Event { readonly attribute string text; }; interface BinaryFileReaderLoadEvent : Event { readonly attribute array bytes; }; interface FileReaderException : DOMException { readyonly attribute unsigned short code; }; // const unsigned short NOT_FOUND_ERR = 1; // const unsigned short ACCESS_DENIED_ERR = 2; // const unsigned short ORIGIN_VIOLATION_ERR = 3; // const unsigned short READ_ERROR_ERR = 4; interface FileReaderErrorEvent : Event { readonly attribute FileReaderException error; }; All the objects should be exposed on the window object so one can extend/override them with prototypes and getters etc. if desired. There'd by no sync version, only async like the examples above. I don't think progress events and reading the file in chunks are needed for this simple API. I also specifically left out xml parsing, as that can be done with DOMParser once you get the file text. (If DOMParser has shortcomings, it should be improved.) As for the encoding used for TextFileReader when reading the file, not sure. I expect it to work just like document.load, XHR (with file://) and DOM3 Load & Save work. If you try to use a FileReader on a protocol besides file://, you'd get the ORIGIN_VIOLATION_ERR in the error listener. (Note that file://bark/dir/test.html <- and file://meow/dir/file.txt would be a cross-origin violation for example.) You'd also get the ORIGIN_VIOLATION_ERR in the error listener if you try to use a FileReader on a non-file:// page. Error handling is very important. -- Not for debugging, but for the user-informative 'why things went wrong'. I absolutely hate it when a generic exception is thrown and you can't tell if the file was not found or if there's a cross-origin security error for example (like Firefox does for XHR's open() when you specify a URI to a non-existent file). It makes it difficult to give info on what went wrong. That's the basic idea. And, there could always be other readers like Base64FileReader and DataURIFileReader later on. There could even be an XMLFileReader (if you didn't want to create one yourself by wrapping the text reader and using DOMParser). I would also expect FileWriter objects, but saving that for later. Now, with regards to the FileAPI, I see that it has objects and methods for reading files. However, I don't currently see a way to get a files object that has an entry that points to a file without using <input type="file">. If there was a way though to load a local file on a local web page directly (without user-interaction and without <input type="file">) in JS with the FileAPI, maybe none of this is needed. Finally, I have to say that for the treader and breader examples above, I really love the idea of things working just like that. -- Michael
Received on Tuesday, 18 August 2009 02:38:30 UTC