- From: Robin Berjon via cvs-syncmail <cvsmail@w3.org>
- Date: Thu, 03 Dec 2009 17:38:26 +0000
- To: public-dap-commits@w3.org
Update of /sources/public/2009/dap/file-system In directory hutz:/tmp/cvs-serv7261 Added Files: file-writer.html Log Message: first stab at a brain dump on File Writer --- NEW FILE: file-writer.html --- <!DOCTYPE html> <html> <head> <title>File API: Writer</title> <meta http-equiv='Content-Type' content='text/html;charset=utf-8'/> <script src='../ReSpec.js/js/respec.js' class='remove'></script> <script class='remove'> var respecConfig = { specStatus: "ED", shortName: "file-writer-api", // publishDate: "2009-08-06", // previousPublishDate: "1977-03-15", edDraftURI: "http://dev.w3.org/2009/dap/file-system/file-writer.html", // lcEnd: "2009-08-05", noIDLIn: true, editors: [ { name: "Robin Berjon", url: "http://berjon.com/", company: "Vodafone", companyURL: "http://vodafone.com/" }, ], }; </script> <script src='../common/config.js' class='remove'></script> </head> <body> <section id='abstract'> This specification defines an <acronym title='Application Programming Interface'>API</acronym> to write to files. <!-- XXX explain how it fits with File API --> </section> <section id='conformance'> <p> This specification defines conformance criteria that apply to a single product: <dfn>user agents</dfn> that implement the interfaces that it contains. </p> <div class='issue'> <p> If different user agents obtain writers in different ways we will need to add more classes, or some way to handle the variability. </p> </div> </section> <section class='informative'> <h2>Introduction</h2> <p> ... </p> <!-- XXX be clear that it may be remote writing sources be clear that it may look different from typical to fit inside security constraints - look at cut and paste - look at BinaryArray - go over emails on WebApps about use cases again --> <section> <h2>General Issues</h2> <div class='issues'> <p> Do we need async writers? There are further details about options for this below. </p> <p> Do we need a way to remove chars/bytes from the middle of a file without rewriting it completely? </p> <p> We need to add a lot of definitions, and generally tighten up the prose. </p> </div> </section> <section> <h2>Examples</h2> <p> Here is a simple comment that writes a text file: </p> <pre class='example sh_javascript'> function sucCB (tw) { for (var i = 0; i < 10; i++) { tw.print("I am dahut number " . i . "\n"); } tw.close(); } function errCB (err) { alert("There was an error opening the file."); } navigator.device.textWriter("text/plain", sucCB, "dahut.txt", { endings: "crlf" }, errCB); </pre> </section> </section> <section> <h2>Obtaining file writers</h2> <p> There are several ways in which writer can be obtained. Not all <a>user agents</a> may in fact implement all of them. </p> <section class='informative'> <h2>Security Considerations</h2> <p> Within a browser <a>user agent</a>, the request for a writer through the <a>Device</a> API may for instance trigger a dialog very similar to the one users see when downloading a file, which in turn can cause a file save dialog to show. Relying on a common metaphor with similar security issues can help make sure that users are as cautious as they are with downloaded file, and helps reuse the existing checking toolset. </p> <p> Most of the security issues pertaining to writing to a file on the user's drive are the same as the ones involved in downloading arbitrary files from the Internet. The primary difference stems from the fact that the file may be continuously written and re-written, at least until such a time as it is deemed closed by the user agent. This has an impact on size quota on one side, and on processes that may require analysing the content of the file. </p> <p> So long as <code>save</code> has not been called on the writer object and there are modifications being made to the file, the <a>user agent</a> should keep the content in a separate temporary file as sometimes happens during download. Upon calling <code>save</code>, the temporary file would replace the permanent one. If the <a>user agent</a> runs a security mechanism such as a virus checker, this step is likely the right one to do so. </p> <p> Where quotas are concerned, <a>user agents</a> should monitor the size of the file(s) being written and possibly interrupt the script and warn the user if certain limits of file size or remaining space are reached. </p> <p> Other parts of the download protection tool-chain such as flagging files as "unsafe to open" or refusing to create dangerous file names (or file names with extensions that do not match the media type) should naturally be applied. </p> </section> <section> <h2>Requesting writers from the Device interface</h2> <section> <h2>The <code>Device</code> interface</h2> <p> The <a>Device</a> interface is typically exposed on the <code>navigator.device</code> object, as defined in [[!CORE-DEVICE]]. </p> <div class='idl' title='Device implements DeviceWriter'></div> <dl title='[Supplemental, NoInterfaceObject] interface DeviceWriter' class='idl'> <dt>PendingOp textWriter ()</dt> <dd> <p> This method is used to request a writer for text documents. It begins an asynchronous process that results either in obtaining the right to write to a file (in which case <code>twCB</code> is called), or in that request being denied (in which case <code>errCB</code> is called). </p> <dl class='parameters'> <dt>DOMString mediaType</dt> <dd> This is the media type that describes the content of the file, without media type parameters. If it is an invalid media type, or if it has parameters, the operation MUST abort and call the <code>errCB</code> callback. </dd> <dt>TextWriterCB twCB</dt> <dd> The callback that is called when the writer is accepted. </dd> <dt>optional DOMString name</dt> <dd> The name of the file (without any path component). The <a>user agent</a> MAY choose to ignore this choice of name, or to modify it. </dd> <dt>optional TextOptions opt</dt> <dd> Options that define how the text is written. </dd> <dt>optional ErrorCB errCB</dt> <dd> A callback that is called when errors happen, or when the request to obtain a file writer is denied. </dd> </dl> </dd> <dt>PendingOp binaryWriter ()</dt> <dd> <p> This method is used to request a writer for binary documents. </p> <dl class='parameters'> <dt>DOMString mediaType</dt> <dd> This is the media type that describes the content of the file, without media type parameters. If it is an invalid media type, or if it has parameters, the operation MUST abort and call the <code>errCB</code> callback. </dd> <dt>BinaryWriterCB bwCB</dt> <dd> The callback that is called when the writer is accepted. </dd> <dt>optional DOMString name</dt> <dd> The name of the file (without any path component). The <a>user agent</a> MAY choose to ignore this choice of name, or to modify it. </dd> <dt>optional ErrorCB errCB</dt> <dd> A callback that is called when errors happen, or when the request to obtain a file writer is denied. </dd> </dl> </dd> </dl> </section> <section> <h2>The <code>TextOptions</code> interface</h2> <p> The following interface is used to specify options for textual writing: </p> <dl title='[NoInterfaceObject] interface TextOptions' class='idl'> <dt>attribute DOMString endings</dt> <dd> <p> How strings containing <code>\n</code> are to be written out. There possible values are: </p> <table class='simple'> <tr><th>Value</th><th>Description</th></tr> <tr> <td>transparent</td> <td> Code points from the string remain untouched. This is the default value. </td> </tr> <tr> <td>native</td> <td> Line-endings are handled according to the platform's preference. </td> </tr> <tr> <td>lf</td> <td> A <code>LF</code> is used. This is the same as is used in Unix systems, as well as Apple OS X. </td> </tr> <tr> <td>cr</td> <td> A <code>CR</code> is used. This is the same as was used in antique Macintosh systems. </td> </tr> <tr> <td>crlf</td> <td> A <code>CRLF</code> pair is used. This is the same as on Microsoft Windows systems. </td> </tr> </table> </dd> <dt>attribute DOMString encoding</dt> <dd> <p> The encoding that is used to write out to the file. The default value is <code>UTF-8</code>. A <a>user agent</a> is not required to support other encodings. </p> <div class='issue'> <p> It may be preferable if we required support for UTF-16 BE/LE, and perhaps for ISO-8859-1 as well (especially if they're supported anyway). </p> </div> </dd> </dl> </section> <section> <h2>The <code>TextWriterCB</code> interface</h2> <p> When <code>textWriter()</code> succeeds, the following callback is made: </p> <dl title='[NoInterfaceObject, Callback=FunctionOnly] interface TextWriterCB' class='idl'> <dt>void onSuccess ()</dt> <dd> <p> The writer was successfully obtained. </p> <dl class='parameters'> <dt>TextWriter tw</dt> <dd> The writer to be used. </dd> </dl> </dd> </dl> </section> <section> <h2>The <code>BinaryWriterCB</code> interface</h2> <p> When <code>binaryWriter()</code> succeeds, the following callback is made: </p> <dl title='[NoInterfaceObject, Callback=FunctionOnly] interface BinaryWriterCB' class='idl'> <dt>void onSuccess ()</dt> <dd> <p> The writer was successfully obtained. </p> <dl class='parameters'> <dt>BinaryWriter bw</dt> <dd> The writer to be used. </dd> </dl> </dd> </dl> </section> <section> <h2>The <code>ErrorCB</code> interface</h2> <p> When either <code>textWriter()</code> or <code>binaryWriter()</code> fails, or when a bad parameter is passed to them, the following callback is made: </p> <dl title='[NoInterfaceObject, Callback=FunctionOnly] interface ErrorCB' class='idl'> <dt>void onError ()</dt> <dd> <p> The writer was not obtained, either because invalid parameters were provided, or because the request to obtain a writer was denied. </p> <dl class='parameters'> <dt>WriterError err</dt> <dd> The error that was generated. </dd> </dl> </dd> </dl> </section> <section> <h2>The <code>WriterError</code> interface</h2> <p> The error is defined as follows: </p> <dl title='[NoInterfaceObject] interface WriterError' class='idl'> <dt>const unsigned short DENIED_ERR = 1</dt> <dd> The request to obtain a writer was denied. </dd> <dt>const unsigned short MEDIA_TYPE_ERR = 2</dt> <dd> The provided media type was invalid, or contained media type parameters. </dd> <dt>readonly attribute unsigned short code</dt> <dd> The code specifying the type of this error. </dd> </dl> </section> </section> <section> <h2>Obtaining a writer through an input element</h2> <p> An additional <code>writable</code> attribute is added to [[!HTML5]] <code>input</code> elements in the <a href='http://dev.w3.org/html5/spec/forms.html#file-upload-state'>file upload state</a>. When present, the <a>user agent</a> SHOULD provide an interface similar to that which is used for regular file upload, and MUST provide a way for the user to accept making the file writable (e.g. by providing a check box enabling it, unchecked by default). </p> <p> The values of the <code>writable</code> attribute are "text" and "binary". If the attribute is present but with a value other than these, the <a>user agent</a> MUST ignore it. </p> <p> If the writability of the files has been accepted, the <a>user agent</a> MUST produce a <code>FileList</code> as per [[!FILE-API]], and items in the <code>FileList</code> MUST be of type <a>TextWriter</a> or <a>BinaryWriter</a> if the value of <code>writable</code> was "text" or binary, respectively. </p> <div class='issue'> <p> It is not clear that this way of selecting between text and binary is good. We could perhaps provide an "auto" value that would use the file type; or just make <code>writable</code> a boolean attribute, return <a>FileWriter</a>s in the <code>FileList</code>, and provide a way of casting. </p> </div> <div class='issue'> <p> This is not necessarily very elegant. Another option would be to not touch input at all, and in order to address the use case of loading a file to be saved provide variants of <code>textWriter</code> and <code>binaryWriter</code> that could take the file object and go through the download prompting defaulting to that file being selected, with the "Careful you're going to overwrite" well-known platform prompt. It would likely render the name and mediaType parameters useless. </p> </div> </section> <section> <h2>Integration with cut & paste and drag & drop</h2> <!-- XXX TBD --> <div class='issue'> <p>@@ TDB @@</p> </div> </section> </section> <section> <h2>File Writing Interfaces</h2> <section> <h2>The <code>FileWriter</code> interface</h2> <p> This interface is never accessed directly, but serves as the base class for <a>TextWriter</a> and <a>BinaryWriter</a>. It inherits from the <code>File</code> interface defined in [[!FILE-API]]. </p> <dl title='[NoInterfaceObject] interface FileWriter : File' class='idl'> <dt>readonly attribute unsigned long long length</dt> <dd> The size of the file in characters for <a>TextWriter</a> and bytes for <a>BinaryWriter</a>. </dd> <dt>readonly attribute unsigned long long position</dt> <dd> The current writing position in the file, measured in characters for <a>TextWriter</a> and bytes for <a>BinaryWriter</a>. </dd> <dt>void seek ()</dt> <dd> <p> Place the current position in the file to the specified value. Subsequent writes will insert their content at that position. </p> <dl class='parameters'> <dt>long long position</dt> <dd> The new position to which to seek, measured in characters for <a>TextWriter</a> and bytes for <a>BinaryWriter</a>. If it is negative, it is counted backwards from the end of the file. If it is positive and superior to <code>length</code>, it is set to the end of the file. If it is negative and absolutely superior to <code>length</code>, it is set to 0. </dd> </dl> </dd> <dt>void truncate ()</dt> <dd> <p> Truncates the file such that its size is reduced to that which is specified, the remaining content being discarded. </p> <dl class='parameters'> <dt>unsigned long long size</dt> <dd> The size to which the file is truncated, measured in characters for <a>TextWriter</a> and bytes for <a>BinaryWriter</a>. If it is greater than <code>length</code>, nothing happens. </dd> </dl> </dd> <dt>readonly attribute boolean saved</dt> <dd> Indicates whether the file is in a saved state or not. When a writer is created, this is set to <code>false</code>, and is further reset to <code>false</code> whenever a write operation is performed. It is set to <code>true</code> after a call to <code>save()</code>. </dd> <dt>void save ()</dt> <dd> <p> Indicate that the file is in a consistent state and good to be read. This does not close the file as more data may yet be written, but it marks it as usable. </p> <div class='issue'> <p> Should this be asynchronous so that networked files (or simply slow supports) can be supported with writes being synched regularly? Should it be renamed <code>sync</code> (and likewise for <code>saved</code>/<code>synched</code>)? </p> </div> </dd> <dt>readonly attribute boolean open</dt> <dd> Indicates whether the file is open and therefore may be written to. When the writer is created, this is set to <code>true</code>. It is switched to <code>false</code> after a call to <code>close()</code>, after which point write operations raise exceptions. </dd> <dt>void close ()</dt> <dd> <p> Indicate that the file will no longer be written to. Implies <code>save()</code>. </p> <div class='issue'> <p> If <code>save()</code> becomes async, then this does too. </p> </div> </dd> </dl> </section> <section> <h2>The <code>TextWriter</code> interface</h2> <p> This interface is used to write to textual files. </p> <dl title='[NoInterfaceObject] interface TextWriter : FileWriter' class='idl'> <dt>void print ()</dt> <dd> <p> Writes the supplied characters at the current file position, using the encoding and line-endings defined in <a>TextOptions</a>. </p> <dl class='parameters'> <dt>DOMString text</dt> <dd> The text to be written. </dd> </dl> <dl class='exception' title='WriteException'> <dt>FILE_CLOSED_ERR</dt> <dd> The file is closed and therefore cannot be written to. </dd> </dl> </dd> </dl> </section> <section> <h2>The <code>BinaryWriter</code> interface</h2> <p> This interface is used to write to binary files, using the <code>Blob</code> interface defined in [[!FILE-API]]. </p> <dl title='[NoInterfaceObject] interface BinaryWriter : FileWriter' class='idl'> <dt>void write ()</dt> <dd> <p> Writes the supplied bytes at the current file position. </p> <dl class='parameters'> <dt>Blob data</dt> <dd> The data to be written. </dd> </dl> <dl class='exception' title='WriteException'> <dt>FILE_CLOSED_ERR</dt> <dd> The file is closed and therefore cannot be written to. </dd> </dl> </dd> </dl> </section> <section> <h2>The <code>WriteException</code> exception</h2> <p> This exception can be raised with different codes on write operations. </p> <dl title='[NoInterfaceObject] exception WriteException' class='idl'> <dt>const unsigned short FILE_CLOSED_ERR = 1</dt> <dd> An attempt to write was made to a file that is closed. </dd> </dl> </section> </section> <section class='appendix'> <h2>Acknowledgements</h2> <p> Many thanks to OMTP BONDI who provided input for this API, based on an initial effort by Opera, and to Arun for his excellent work on the File API. </p> </section> </body> </html>
Received on Thursday, 3 December 2009 17:38:36 UTC