From cdf4a6dfa0a663a604ffa2c45ba72783773eb423 Mon Sep 17 00:00:00 2001 From: Chris Mills Date: Mon, 5 Dec 2022 11:58:57 +0000 Subject: [PATCH 1/4] add getDirectory() and other assorted changes related to OPFS --- .../web/api/file_system_access_api/index.md | 23 ++++--- .../entries/index.md | 4 +- .../getdirectoryhandle/index.md | 2 +- .../getfilehandle/index.md | 2 +- .../api/filesystemdirectoryhandle/index.md | 6 +- .../filesystemdirectoryhandle/keys/index.md | 2 +- .../removeentry/index.md | 2 +- .../resolve/index.md | 2 +- .../filesystemdirectoryhandle/values/index.md | 2 +- .../createsyncaccesshandle/index.md | 4 +- .../api/filesystemhandle/issameentry/index.md | 2 +- .../web/api/filesystemhandle/kind/index.md | 2 +- .../web/api/filesystemhandle/name/index.md | 2 +- .../api/filesystemsyncaccesshandle/index.md | 2 +- .../api/storagemanager/getdirectory/index.md | 66 +++++++++++++++++++ files/en-us/web/api/storagemanager/index.md | 2 + files/jsondata/GroupData.json | 3 +- 17 files changed, 103 insertions(+), 25 deletions(-) create mode 100644 files/en-us/web/api/storagemanager/getdirectory/index.md diff --git a/files/en-us/web/api/file_system_access_api/index.md b/files/en-us/web/api/file_system_access_api/index.md index 0ea7bd8a36bca4d..d982a1d2b59c1a6 100644 --- a/files/en-us/web/api/file_system_access_api/index.md +++ b/files/en-us/web/api/file_system_access_api/index.md @@ -27,23 +27,30 @@ This API allows interaction with files on a user's local device, or on a user-ac Most of the interaction with files and directories is accomplished through handles. A parent {{domxref('FileSystemHandle')}} class helps define two child classes: {{domxref('FileSystemFileHandle')}} and {{domxref('FileSystemDirectoryHandle')}}, for files and directories respectively. -The handles represent a file or directory on the user's system. You can first gain access to them by showing the user a file or directory picker. The methods which allow this are {{domxref('window.showOpenFilePicker')}} and {{domxref('window.showDirectoryPicker')}}. Once these are called, the file picker presents itself and the user selects either a file or directory. Once this happens successfully, a handle is returned. You can also gain access to file handles via the {{domxref('DataTransferItem.getAsFileSystemHandle()')}} method of the {{domxref('HTML Drag and Drop API')}}. +The handles represent a file or directory on the user's system. You can first gain access to them by showing the user a file or directory picker using methods such as {{domxref('window.showOpenFilePicker()')}} and {{domxref('window.showDirectoryPicker()')}}. Once these are called, the file picker presents itself and the user selects either a file or directory. Once this happens successfully, a handle is returned. You can also gain access to file handles via the {{domxref('DataTransferItem.getAsFileSystemHandle()')}} method of the {{domxref('HTML Drag and Drop API', 'HTML Drag and Drop API', '', 'nocode')}}. -The interface {{domxref('FileSystemSyncAccessHandle')}} is also available to define a high-performance handle for _synchronous_ read/write operations (the other handle types are asynchronous). The synchronous nature of this class brings performance advantages intended for use in contexts where asynchronous operations come with high overhead (e.g., [WebAssembly](/en-US/docs/WebAssembly)). Note that it is only usable inside dedicated [Web Workers](/en-US/docs/Web/API/Web_Workers_API), for files within the [origin private file system](https://fs.spec.whatwg.org/#origin-private-file-system). {{domxref('FileSystemSyncAccessHandle')}} is accessed via the {{domxref('FileSystemFileHandle.createSyncAccessHandle', 'createSyncAccessHandle()')}} method. +Each handle provides its own functionality and there are a few differences depending on which one you are using (see the [interfaces](#interfaces) section for specific details). You then can access file data, or information (including children) of the directory selected. This API opens up potential functionality the web has been lacking. Still, security has been of utmost concern when designing the API, and access to file/directory data is disallowed unless the user specifically permits it. + +> **Note:** The different exceptions that can be thrown when using the features of this API are listed on relevant pages as defined in the spec. However, the situation is made more complex by the interaction of the API and the underlying operating system. A proposal has been made to [list the error mappings in the spec](https://github.com/whatwg/fs/issues/57), which includes useful related information. + +### Origin private file system + +The [origin private file system (OPFS)](https://fs.spec.whatwg.org/#origin-private-file-system) is a storage endpoint private to the origin of the page, providing optional access to a special kind of file that is highly optimized for performance, for example, by offering in-place and exclusive write access to a file's content. There are currently two ways to use files within the OPFS: + +- The {{domxref("StorageManager.getDirectory()")}} method returns a reference to a {{domxref("FileSystemDirectoryHandle")}} object allowing access to a directory and its contents, stored in the OPFS. +- The interface {{domxref('FileSystemSyncAccessHandle')}} defines a high-performance handle for _synchronous_ read/write operations (the other handle types are asynchronous). The synchronous nature of this class brings performance advantages intended for use in contexts where asynchronous operations come with high overhead (e.g., [WebAssembly](/en-US/docs/WebAssembly)). Note that it is only usable inside dedicated [Web Workers](/en-US/docs/Web/API/Web_Workers_API), for files within the [origin private file system](#origin_private_file_system). {{domxref('FileSystemSyncAccessHandle')}} is accessed via the {{domxref('FileSystemFileHandle.createSyncAccessHandle', 'createSyncAccessHandle()')}} method. > **Note:** Writes performed using {{domxref('FileSystemSyncAccessHandle.write()')}} are in-place, meaning that changes are written to the actual underlying file at the same time as they are written to the writer. This is not the case with other writing mechanisms available in this API (e.g. {{domxref('FileSystemFileHandle.createWritable()')}}), where changes are not committed to disk until the writing stream is closed. -Each handle provides its own functionality and there are a few differences depending on which one you are using (see the [interfaces](#interfaces) section for specific details). You then can access file data, or information (including children) of the directory selected. +While browsers typically implement this by persisting the contents of the OPFS to disk somewhere, it is not intended that the contents be easily user-accessible. While the browser might make it seem that there are files, they might be stored in a database or any other data structure. You cannot expect to find the created files matched one-to-one somewhere on the hard disk. + +### Saving files There is also "save" functionality: - In the case of the asynchronous handles, use the {{domxref('FileSystemWritableFileStream')}} interface. Once the data you'd like to save is in a format of {{domxref('Blob')}}, {{jsxref("String")}} object, string literal or {{jsxref('ArrayBuffer', 'buffer')}}, you can open a stream and save the data to a file. This can be the existing file or a new file. - In the case of the synchronous {{domxref('FileSystemSyncAccessHandle')}}, you write changes to a file using the {{domxref('FileSystemSyncAccessHandle.write', 'write()')}} method. You can optionally also call {{domxref('FileSystemSyncAccessHandle.flush', 'flush()')}} if you need the changes committed to disk at a specific time (otherwise you can leave the underlying operating system to handle this when it sees fit, which should be OK in most cases). -This API opens up potential functionality the web has been lacking. Still, security has been of utmost concern when designing the API, and access to file/directory data is disallowed unless the user specifically permits it. - -> **Note:** The different exceptions that can be thrown when using the features of this API are listed on relevant pages as defined in the spec. However, the situation is made more complex by the interaction of the API and the underlying operating system. A proposal has been made to [list the error mappings in the spec](https://github.com/whatwg/fs/issues/57), which includes useful related information. - ## Interfaces - {{domxref("FileSystemHandle")}} @@ -53,7 +60,7 @@ This API opens up potential functionality the web has been lacking. Still, secur - {{domxref("FileSystemDirectoryHandle")}} - : provides a handle to a file system directory. - {{domxref("FileSystemSyncAccessHandle")}} - - : Provides a synchronous handle to a file system entry, which operates in-place on a single file on disk. The synchronous nature of the file reads and writes allows for higher performance for critical methods in contexts where asynchronous operations come with high overhead, e.g., [WebAssembly](/en-US/docs/WebAssembly). This class is only accessible inside dedicated [Web Workers](/en-US/docs/Web/API/Web_Workers_API) for files within the [origin private file system](https://fs.spec.whatwg.org/#origin-private-file-system). + - : Provides a synchronous handle to a file system entry, which operates in-place on a single file on disk. The synchronous nature of the file reads and writes allows for higher performance for critical methods in contexts where asynchronous operations come with high overhead, e.g., [WebAssembly](/en-US/docs/WebAssembly). This class is only accessible inside dedicated [Web Workers](/en-US/docs/Web/API/Web_Workers_API) for files within the [origin private file system](#origin_private_file_system). - {{domxref("FileSystemWritableFileStream")}} - : is a {{domxref('WritableStream')}} object with additional convenience methods, which operates on a single file on disk. diff --git a/files/en-us/web/api/filesystemdirectoryhandle/entries/index.md b/files/en-us/web/api/filesystemdirectoryhandle/entries/index.md index b016c053c95e3b3..0ef1588264bfb0c 100644 --- a/files/en-us/web/api/filesystemdirectoryhandle/entries/index.md +++ b/files/en-us/web/api/filesystemdirectoryhandle/entries/index.md @@ -12,12 +12,12 @@ tags: browser-compat: api.FileSystemDirectoryHandle.entries --- -{{securecontext_header}}{{DefaultAPISidebar("File System Access API")}} +{{securecontext_header}}{{APIRef("File System Access API")}} The **`entries()`** method of the {{domxref("FileSystemDirectoryHandle")}} interface returns an array of a given object's own enumerable property `[key, value]` pairs, in the same order as that -provided by a {{jsxref('for...in')}} loop (the difference being that a for-in loop +provided by a [`for...in`](/en-US/docs/Web/JavaScript/Reference/Statements/for...in) loop (the difference being that a for-in loop enumerates properties in the prototype chain as well). ## Syntax diff --git a/files/en-us/web/api/filesystemdirectoryhandle/getdirectoryhandle/index.md b/files/en-us/web/api/filesystemdirectoryhandle/getdirectoryhandle/index.md index 45b4fe5073f5864..c42fd6619b492fe 100644 --- a/files/en-us/web/api/filesystemdirectoryhandle/getdirectoryhandle/index.md +++ b/files/en-us/web/api/filesystemdirectoryhandle/getdirectoryhandle/index.md @@ -12,7 +12,7 @@ tags: browser-compat: api.FileSystemDirectoryHandle.getDirectoryHandle --- -{{securecontext_header}}{{DefaultAPISidebar("File System Access API")}} +{{securecontext_header}}{{APIRef("File System Access API")}} The **`getDirectoryHandle()`** method of the {{domxref("FileSystemDirectoryHandle")}} interface returns a diff --git a/files/en-us/web/api/filesystemdirectoryhandle/getfilehandle/index.md b/files/en-us/web/api/filesystemdirectoryhandle/getfilehandle/index.md index c819b66a77b92ee..d34f92e6557740b 100644 --- a/files/en-us/web/api/filesystemdirectoryhandle/getfilehandle/index.md +++ b/files/en-us/web/api/filesystemdirectoryhandle/getfilehandle/index.md @@ -11,7 +11,7 @@ tags: browser-compat: api.FileSystemDirectoryHandle.getFileHandle --- -{{securecontext_header}}{{DefaultAPISidebar("File System Access API")}} +{{securecontext_header}}{{APIRef("File System Access API")}} The **`getFileHandle()`** method of the {{domxref("FileSystemDirectoryHandle")}} interface returns a diff --git a/files/en-us/web/api/filesystemdirectoryhandle/index.md b/files/en-us/web/api/filesystemdirectoryhandle/index.md index e1fbdf63e6efd6a..971ee515ec2f877 100644 --- a/files/en-us/web/api/filesystemdirectoryhandle/index.md +++ b/files/en-us/web/api/filesystemdirectoryhandle/index.md @@ -13,9 +13,11 @@ tags: browser-compat: api.FileSystemDirectoryHandle --- -{{securecontext_header}}{{DefaultAPISidebar("File System Access API")}} +{{securecontext_header}}{{APIRef("File System Access API")}} -The **`FileSystemDirectoryHandle`** interface of the {{domxref('File System Access API')}} provides a handle to a file system directory. The interface is accessed via the {{domxref('window.showDirectoryPicker()')}} method. +The **`FileSystemDirectoryHandle`** interface of the {{domxref('File System Access API')}} provides a handle to a file system directory. + +The interface can be accessed via the {{domxref('window.showDirectoryPicker()')}} and {{domxref('StorageManager.getDirectory()')}} methods. {{InheritanceDiagram}} diff --git a/files/en-us/web/api/filesystemdirectoryhandle/keys/index.md b/files/en-us/web/api/filesystemdirectoryhandle/keys/index.md index 70775811372f9c0..a42c6ad55bd6f3d 100644 --- a/files/en-us/web/api/filesystemdirectoryhandle/keys/index.md +++ b/files/en-us/web/api/filesystemdirectoryhandle/keys/index.md @@ -12,7 +12,7 @@ tags: browser-compat: api.FileSystemDirectoryHandle.keys --- -{{securecontext_header}}{{DefaultAPISidebar("File System Access API")}} +{{securecontext_header}}{{APIRef("File System Access API")}} The **`keys()`** method of the {{domxref("FileSystemDirectoryHandle")}} interface returns a new _array iterator_ diff --git a/files/en-us/web/api/filesystemdirectoryhandle/removeentry/index.md b/files/en-us/web/api/filesystemdirectoryhandle/removeentry/index.md index 0c05931c2f2089b..dedf6b5bfa7e9fa 100644 --- a/files/en-us/web/api/filesystemdirectoryhandle/removeentry/index.md +++ b/files/en-us/web/api/filesystemdirectoryhandle/removeentry/index.md @@ -11,7 +11,7 @@ tags: browser-compat: api.FileSystemDirectoryHandle.removeEntry --- -{{securecontext_header}}{{DefaultAPISidebar("File System Access API")}} +{{securecontext_header}}{{APIRef("File System Access API")}} The **`removeEntry()`** method of the {{domxref("FileSystemDirectoryHandle")}} interface attempts to remove an entry if the diff --git a/files/en-us/web/api/filesystemdirectoryhandle/resolve/index.md b/files/en-us/web/api/filesystemdirectoryhandle/resolve/index.md index d61e8d6873bd187..aac192879e57347 100644 --- a/files/en-us/web/api/filesystemdirectoryhandle/resolve/index.md +++ b/files/en-us/web/api/filesystemdirectoryhandle/resolve/index.md @@ -11,7 +11,7 @@ tags: browser-compat: api.FileSystemDirectoryHandle.resolve --- -{{securecontext_header}}{{DefaultAPISidebar("File System Access API")}} +{{securecontext_header}}{{APIRef("File System Access API")}} The **`resolve()`** method of the {{domxref("FileSystemDirectoryHandle")}} interface returns an {{jsxref('Array')}} of diff --git a/files/en-us/web/api/filesystemdirectoryhandle/values/index.md b/files/en-us/web/api/filesystemdirectoryhandle/values/index.md index 3006daf8018d7dc..58cd2075f1a3355 100644 --- a/files/en-us/web/api/filesystemdirectoryhandle/values/index.md +++ b/files/en-us/web/api/filesystemdirectoryhandle/values/index.md @@ -12,7 +12,7 @@ tags: browser-compat: api.FileSystemDirectoryHandle.values --- -{{securecontext_header}}{{DefaultAPISidebar("File System Access API")}} +{{securecontext_header}}{{APIRef("File System Access API")}} The **`values()`** method of the {{domxref("FileSystemDirectoryHandle")}} interface returns a new _array iterator_ diff --git a/files/en-us/web/api/filesystemfilehandle/createsyncaccesshandle/index.md b/files/en-us/web/api/filesystemfilehandle/createsyncaccesshandle/index.md index e211443b35cd34b..099566ac8a50675 100644 --- a/files/en-us/web/api/filesystemfilehandle/createsyncaccesshandle/index.md +++ b/files/en-us/web/api/filesystemfilehandle/createsyncaccesshandle/index.md @@ -18,7 +18,7 @@ browser-compat: api.FileSystemFileHandle.createSyncAccessHandle The **`createSyncAccessHandle()`** method of the {{domxref("FileSystemFileHandle")}} interface returns a {{jsxref('Promise')}} which resolves to a {{domxref('FileSystemSyncAccessHandle')}} object that can be used to synchronously read from and write to a file. The synchronous nature of this method brings performance advantages, -but it is only usable inside dedicated [Web Workers](/en-US/docs/Web/API/Web_Workers_API) for files within the [origin private file system](https://fs.spec.whatwg.org/#origin-private-file-system). +but it is only usable inside dedicated [Web Workers](/en-US/docs/Web/API/Web_Workers_API) for files within the [origin private file system](/en-US/docs/Web/API/File_System_Access_API#origin_private_file_system). Creating a {{domxref('FileSystemSyncAccessHandle')}} takes an exclusive lock on the file associated with the file handle. This prevents the creation of further {{domxref('FileSystemSyncAccessHandle')}}s or {{domxref('FileSystemWritableFileStream')}}s for the file until the existing access handle is closed. @@ -39,7 +39,7 @@ A {{jsxref('Promise')}} which resolves to a {{domxref('FileSystemSyncAccessHandl ### Exceptions - `InvalidStateError` {{domxref("DOMException")}} - - : Thrown if the {{domxref('FileSystemSyncAccessHandle')}} object does not represent a file in the [origin private file system](https://fs.spec.whatwg.org/#origin-private-file-system). + - : Thrown if the {{domxref('FileSystemSyncAccessHandle')}} object does not represent a file in the [origin private file system](/en-US/docs/Web/API/File_System_Access_API#origin_private_file_system). - `NoModificationAllowedError` {{domxref("DOMException")}} - : Thrown if the browser is not able to acquire a lock on the file associated with the file handle. - `NotAllowedError` {{domxref("DOMException")}} diff --git a/files/en-us/web/api/filesystemhandle/issameentry/index.md b/files/en-us/web/api/filesystemhandle/issameentry/index.md index 4100faa0b2ae42d..c3971f9984933cb 100644 --- a/files/en-us/web/api/filesystemhandle/issameentry/index.md +++ b/files/en-us/web/api/filesystemhandle/issameentry/index.md @@ -11,7 +11,7 @@ tags: browser-compat: api.FileSystemHandle.isSameEntry --- -{{securecontext_header}}{{DefaultAPISidebar("File System Access API")}} +{{securecontext_header}}{{APIRef("File System Access API")}} The **`isSameEntry()`** method of the {{domxref("FileSystemHandle")}} interface compares two {{domxref("FileSystemHandle", diff --git a/files/en-us/web/api/filesystemhandle/kind/index.md b/files/en-us/web/api/filesystemhandle/kind/index.md index da3ba1bd15b0df1..d9d53e603fa04db 100644 --- a/files/en-us/web/api/filesystemhandle/kind/index.md +++ b/files/en-us/web/api/filesystemhandle/kind/index.md @@ -13,7 +13,7 @@ tags: browser-compat: api.FileSystemHandle.kind --- -{{securecontext_header}}{{DefaultAPISidebar("File System Access API")}} +{{securecontext_header}}{{APIRef("File System Access API")}} The **`kind`** read-only property of the {{domxref("FileSystemHandle")}} interface returns the type of entry. This is diff --git a/files/en-us/web/api/filesystemhandle/name/index.md b/files/en-us/web/api/filesystemhandle/name/index.md index b112fea92b600c0..4cfeaece38a177d 100644 --- a/files/en-us/web/api/filesystemhandle/name/index.md +++ b/files/en-us/web/api/filesystemhandle/name/index.md @@ -12,7 +12,7 @@ tags: browser-compat: api.FileSystemHandle.name --- -{{securecontext_header}}{{DefaultAPISidebar("File System Access API")}} +{{securecontext_header}}{{APIRef("File System Access API")}} The **`name`** read-only property of the {{domxref("FileSystemHandle")}} interface returns the name of the entry represented by diff --git a/files/en-us/web/api/filesystemsyncaccesshandle/index.md b/files/en-us/web/api/filesystemsyncaccesshandle/index.md index 7cdb23d0bc7b319..b9355ec4e1b7fb6 100644 --- a/files/en-us/web/api/filesystemsyncaccesshandle/index.md +++ b/files/en-us/web/api/filesystemsyncaccesshandle/index.md @@ -16,7 +16,7 @@ browser-compat: api.FileSystemSyncAccessHandle The **`FileSystemSyncAccessHandle`** interface of the {{domxref("File System Access API", "File System Access API", "", "nocode")}} represents a synchronous handle to a file system entry. The synchronous nature of the file reads and writes allows for higher performance for critical methods in contexts where asynchronous operations come with high overhead, e.g., [WebAssembly](/en-US/docs/WebAssembly). -This class is only accessible inside dedicated [Web Workers](/en-US/docs/Web/API/Web_Workers_API) for files within the [origin private file system](https://fs.spec.whatwg.org/#origin-private-file-system). +This class is only accessible inside dedicated [Web Workers](/en-US/docs/Web/API/Web_Workers_API) for files within the [origin private file system](/en-US/docs/Web/API/File_System_Access_API#origin_private_file_system). The interface is accessed through the {{domxref('FileSystemFileHandle.createSyncAccessHandle()')}} method. diff --git a/files/en-us/web/api/storagemanager/getdirectory/index.md b/files/en-us/web/api/storagemanager/getdirectory/index.md new file mode 100644 index 000000000000000..6271d48b46e96e0 --- /dev/null +++ b/files/en-us/web/api/storagemanager/getdirectory/index.md @@ -0,0 +1,66 @@ +--- +title: StorageManager.getDirectory() +slug: Web/API/StorageManager/getDirectory +page-type: web-api-instance-method +tags: + - API + - Method + - Quota + - Reference + - Secure context + - Storage + - Storage API + - StorageManager + - Usage + - getDirectory +browser-compat: api.StorageManager.getDirectory +--- + +{{securecontext_header}}{{APIRef("Storage")}} + +The **`getDirectory()`** method of the {{domxref("StorageManager")}} interface is used to obtain a reference to a {{domxref("FileSystemDirectoryHandle")}} object allowing access to a directory and its contents, stored in the [origin private file system](/en-US/docs/Web/API/File_System_Access_API#origin_private_file_system). + +## Syntax + +```js-nolint +getDirectory() +``` + +### Parameters + +None. + +### Return value + +A {{jsxref('Promise')}} that fulfills with a {{domxref("FileSystemDirectoryHandle")}} object. + +## Examples + +```js +async function manipulateDirectory() { + const root = await navigator.storage.getDirectory(); + + // Create a new file handle. + const fileHandle = await root.getFileHandle('Untitled.txt', { create: true }); + + // Create a new directory handle. + const dirHandle = await root.getDirectoryHandle('New Folder', { create: true }); + + // Recursively remove a directory. + await root.removeEntry('Old Stuff', { recursive: true }); +} +``` + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- {{domxref("StorageManager")}} +- {{domxref("navigator.storage")}} +- {{domxref("FileSystemDirectoryHandle")}} diff --git a/files/en-us/web/api/storagemanager/index.md b/files/en-us/web/api/storagemanager/index.md index a0c12e918d4f815..b86ef154fec83e9 100644 --- a/files/en-us/web/api/storagemanager/index.md +++ b/files/en-us/web/api/storagemanager/index.md @@ -24,6 +24,8 @@ The **`StorageManager`** interface of the [Storage API](/en-US/docs/Web/API/Stor - {{domxref("StorageManager.estimate()")}} {{securecontext_inline}} - : Returns a {{jsxref('Promise')}} that resolves to an object containing usage and quota numbers for your origin. +- {{domxref("StorageManager.getDirectory()")}} {{securecontext_inline}} + - : Used to obtain a reference to a {{domxref("FileSystemDirectoryHandle")}} object allowing access to a directory and its contents, stored in the [origin private file system](/en-US/docs/Web/API/File_System_Access_API#origin_private_file_system). Returns a {{jsxref('Promise')}} that fulfills with a {{domxref("FileSystemDirectoryHandle")}} object. - {{domxref("StorageManager.persist()")}} {{securecontext_inline}} - : Returns a {{jsxref('Promise')}} that resolves to `true` if the user agent is able to persist your site's storage. - {{domxref("StorageManager.persisted()")}} {{securecontext_inline}} diff --git a/files/jsondata/GroupData.json b/files/jsondata/GroupData.json index 0cd51d9f6dee2f0..f309f19ddfbed09 100644 --- a/files/jsondata/GroupData.json +++ b/files/jsondata/GroupData.json @@ -462,7 +462,8 @@ "window.showOpenFilePicker()", "window.showSaveFilePicker()", "window.showDirectoryPicker()", - "DataTransferItem.getAsFileSystemHandle()" + "DataTransferItem.getAsFileSystemHandle()", + "StorageManager.getDirectory()" ], "properties": [], "events": [] From 97e1026af64c829ab49cf9552e8fbbb0cbc6f701 Mon Sep 17 00:00:00 2001 From: Chris Mills Date: Mon, 5 Dec 2022 12:37:00 +0000 Subject: [PATCH 2/4] attempt to add an explanation of the getDirectory() security exception --- files/en-us/web/api/storagemanager/getdirectory/index.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/files/en-us/web/api/storagemanager/getdirectory/index.md b/files/en-us/web/api/storagemanager/getdirectory/index.md index 6271d48b46e96e0..c7d559d56815a15 100644 --- a/files/en-us/web/api/storagemanager/getdirectory/index.md +++ b/files/en-us/web/api/storagemanager/getdirectory/index.md @@ -34,6 +34,11 @@ None. A {{jsxref('Promise')}} that fulfills with a {{domxref("FileSystemDirectoryHandle")}} object. +### Exceptions + +- `SecurityError` {{domxref("DOMException")}} + - : Thrown if the user agent is not able to map the requested directory to the local OPFS. + ## Examples ```js From 2ce875e5609b73ba672c7cf54bcefb43526401ad Mon Sep 17 00:00:00 2001 From: Chris Mills Date: Tue, 6 Dec 2022 10:10:02 +0000 Subject: [PATCH 3/4] making fixes for a-sully review comments --- .../web/api/file_system_access_api/index.md | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/files/en-us/web/api/file_system_access_api/index.md b/files/en-us/web/api/file_system_access_api/index.md index d982a1d2b59c1a6..e1f8b25f4b0d974 100644 --- a/files/en-us/web/api/file_system_access_api/index.md +++ b/files/en-us/web/api/file_system_access_api/index.md @@ -27,23 +27,41 @@ This API allows interaction with files on a user's local device, or on a user-ac Most of the interaction with files and directories is accomplished through handles. A parent {{domxref('FileSystemHandle')}} class helps define two child classes: {{domxref('FileSystemFileHandle')}} and {{domxref('FileSystemDirectoryHandle')}}, for files and directories respectively. -The handles represent a file or directory on the user's system. You can first gain access to them by showing the user a file or directory picker using methods such as {{domxref('window.showOpenFilePicker()')}} and {{domxref('window.showDirectoryPicker()')}}. Once these are called, the file picker presents itself and the user selects either a file or directory. Once this happens successfully, a handle is returned. You can also gain access to file handles via the {{domxref('DataTransferItem.getAsFileSystemHandle()')}} method of the {{domxref('HTML Drag and Drop API', 'HTML Drag and Drop API', '', 'nocode')}}. +The handles represent a file or directory on the user's system. You can first gain access to them by showing the user a file or directory picker using methods such as {{domxref('window.showOpenFilePicker()')}} and {{domxref('window.showDirectoryPicker()')}}. Once these are called, the file picker presents itself and the user selects either a file or directory. Once this happens successfully, a handle is returned. + +You can also gain access to file handles via: + +- The {{domxref('DataTransferItem.getAsFileSystemHandle()')}} method of the {{domxref('HTML Drag and Drop API', 'HTML Drag and Drop API', '', 'nocode')}}. +- The [File Handling API](https://developer.chrome.com/en/articles/file-handling/). Each handle provides its own functionality and there are a few differences depending on which one you are using (see the [interfaces](#interfaces) section for specific details). You then can access file data, or information (including children) of the directory selected. This API opens up potential functionality the web has been lacking. Still, security has been of utmost concern when designing the API, and access to file/directory data is disallowed unless the user specifically permits it. > **Note:** The different exceptions that can be thrown when using the features of this API are listed on relevant pages as defined in the spec. However, the situation is made more complex by the interaction of the API and the underlying operating system. A proposal has been made to [list the error mappings in the spec](https://github.com/whatwg/fs/issues/57), which includes useful related information. +> **Note:** Objects based on {{domxref("FileSystemHandle")}} can also be serialized into an {{domxref("IndexedDB API", "IndexedDB", "", "nocode")}} database instance, or transferred via {{domxref("window.postMessage", "postMessage()")}}. + ### Origin private file system -The [origin private file system (OPFS)](https://fs.spec.whatwg.org/#origin-private-file-system) is a storage endpoint private to the origin of the page, providing optional access to a special kind of file that is highly optimized for performance, for example, by offering in-place and exclusive write access to a file's content. There are currently two ways to use files within the OPFS: +The [origin private file system (OPFS)](https://fs.spec.whatwg.org/#origin-private-file-system) is a storage endpoint private to the origin of the page, providing optional access to a special kind of file that is highly optimized for performance, for example, by offering in-place and exclusive write access to a file's content. -- The {{domxref("StorageManager.getDirectory()")}} method returns a reference to a {{domxref("FileSystemDirectoryHandle")}} object allowing access to a directory and its contents, stored in the OPFS. -- The interface {{domxref('FileSystemSyncAccessHandle')}} defines a high-performance handle for _synchronous_ read/write operations (the other handle types are asynchronous). The synchronous nature of this class brings performance advantages intended for use in contexts where asynchronous operations come with high overhead (e.g., [WebAssembly](/en-US/docs/WebAssembly)). Note that it is only usable inside dedicated [Web Workers](/en-US/docs/Web/API/Web_Workers_API), for files within the [origin private file system](#origin_private_file_system). {{domxref('FileSystemSyncAccessHandle')}} is accessed via the {{domxref('FileSystemFileHandle.createSyncAccessHandle', 'createSyncAccessHandle()')}} method. +Files in the OPFS differ from the files that you'd select using a picker. Storing data in the OPFS is similar to storing data in any other browser-provided storage mechanism that's private to the origin of the page (e.g. the {{domxref("IndexedDB API", "IndexedDB API", "", "nocode")}}). -> **Note:** Writes performed using {{domxref('FileSystemSyncAccessHandle.write()')}} are in-place, meaning that changes are written to the actual underlying file at the same time as they are written to the writer. This is not the case with other writing mechanisms available in this API (e.g. {{domxref('FileSystemFileHandle.createWritable()')}}), where changes are not committed to disk until the writing stream is closed. +This means that: + +- Permission prompts are not required to access the files in the OPFS. +- Clearing data for the site deletes the entire OPFS (which isn't the case for non-OPFS files). +- The OFPS is subject to quota restrictions (again, not the case for non-OPFS files). + +Files can be manipulated inside the OPFS via a three-step process: + +1. The {{domxref("StorageManager.getDirectory()")}} method returns a reference to a {{domxref("FileSystemDirectoryHandle")}} object allowing access to a directory and its contents — this represents the root of the OPFS. +2. The {{domxref("FileSystemDirectoryHandle.getFileHandle()")}} method is invoked to return a {{domxref('FileSystemFileHandle')}} object representing a handle to a specific file in the directory. +3. The {{domxref('FileSystemFileHandle.createSyncAccessHandle', 'createSyncAccessHandle()')}} method is invoked on that file handle, and returns a {{domxref('FileSystemSyncAccessHandle')}} object that can be used to read and write to the file. This is a high-performance handle for _synchronous_ read/write operations (the other handle types are asynchronous). The synchronous nature of this class brings performance advantages intended for use in contexts where asynchronous operations come with high overhead (for example, [WebAssembly](/en-US/docs/WebAssembly)). Note that it is only usable inside dedicated [Web Workers](/en-US/docs/Web/API/Web_Workers_API). While browsers typically implement this by persisting the contents of the OPFS to disk somewhere, it is not intended that the contents be easily user-accessible. While the browser might make it seem that there are files, they might be stored in a database or any other data structure. You cannot expect to find the created files matched one-to-one somewhere on the hard disk. +> **Note:** Writes performed using {{domxref('FileSystemSyncAccessHandle.write()')}} are in-place, meaning that changes are written to the actual underlying file at the same time as they are written to the writer. This is not the case with other writing mechanisms available in this API (e.g. {{domxref('FileSystemFileHandle.createWritable()')}}), where changes are not committed to disk until the writing stream is closed. + ### Saving files There is also "save" functionality: From 8b5a4163f18bf1b5bd1671cadb07d15e2082f551 Mon Sep 17 00:00:00 2001 From: Chris Mills Date: Wed, 7 Dec 2022 08:20:48 +0000 Subject: [PATCH 4/4] 2nd round of fixes for a-sully comments --- .../web/api/file_system_access_api/index.md | 10 ++-- .../api/storagemanager/getdirectory/index.md | 46 +++++++++++++++---- 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/files/en-us/web/api/file_system_access_api/index.md b/files/en-us/web/api/file_system_access_api/index.md index e1f8b25f4b0d974..35abb2f80e6caea 100644 --- a/files/en-us/web/api/file_system_access_api/index.md +++ b/files/en-us/web/api/file_system_access_api/index.md @@ -44,13 +44,11 @@ Each handle provides its own functionality and there are a few differences depen The [origin private file system (OPFS)](https://fs.spec.whatwg.org/#origin-private-file-system) is a storage endpoint private to the origin of the page, providing optional access to a special kind of file that is highly optimized for performance, for example, by offering in-place and exclusive write access to a file's content. -Files in the OPFS differ from the files that you'd select using a picker. Storing data in the OPFS is similar to storing data in any other browser-provided storage mechanism that's private to the origin of the page (e.g. the {{domxref("IndexedDB API", "IndexedDB API", "", "nocode")}}). +Storing data in the OPFS is similar to storing data in any other browser-provided storage mechanism that's private to the origin of the page (for example the {{domxref("IndexedDB API", "IndexedDB API", "", "nocode")}}). This means that files in the OPFS differ from files selected using a picker in the following ways: -This means that: - -- Permission prompts are not required to access the files in the OPFS. -- Clearing data for the site deletes the entire OPFS (which isn't the case for non-OPFS files). -- The OFPS is subject to quota restrictions (again, not the case for non-OPFS files). +- Permission prompts are not required to access files in the OPFS. +- Clearing data for the site deletes the OPFS. +- The OFPS is subject to browser quota restrictions. Files can be manipulated inside the OPFS via a three-step process: diff --git a/files/en-us/web/api/storagemanager/getdirectory/index.md b/files/en-us/web/api/storagemanager/getdirectory/index.md index c7d559d56815a15..b2a98e5b512d2c1 100644 --- a/files/en-us/web/api/storagemanager/getdirectory/index.md +++ b/files/en-us/web/api/storagemanager/getdirectory/index.md @@ -18,7 +18,7 @@ browser-compat: api.StorageManager.getDirectory {{securecontext_header}}{{APIRef("Storage")}} -The **`getDirectory()`** method of the {{domxref("StorageManager")}} interface is used to obtain a reference to a {{domxref("FileSystemDirectoryHandle")}} object allowing access to a directory and its contents, stored in the [origin private file system](/en-US/docs/Web/API/File_System_Access_API#origin_private_file_system). +The **`getDirectory()`** method of the {{domxref("StorageManager")}} interface is used to obtain a reference to a {{domxref("FileSystemDirectoryHandle")}} object allowing access to a directory and its contents, stored in the [origin private file system](/en-US/docs/Web/API/File_System_Access_API#origin_private_file_system) (OPFS). ## Syntax @@ -41,21 +41,47 @@ A {{jsxref('Promise')}} that fulfills with a {{domxref("FileSystemDirectoryHandl ## Examples -```js -async function manipulateDirectory() { - const root = await navigator.storage.getDirectory(); +The following asynchronous event handler function is contained inside a Web Worker. On receiving a message from the main thread it: - // Create a new file handle. - const fileHandle = await root.getFileHandle('Untitled.txt', { create: true }); +1. Gets a {{domxref("FileSystemDirectoryHandle")}} representing the root of the OPFS using `getDirectory()`, storing it in the `root` variable. +2. Gets a file handle using {{domxref("FileSystemDirectoryHandle.getFileHandle()")}}. +3. Creates a synchronous file access handle using {{domxref("FileSystemFileHandle.createSyncAccessHandle()")}}. +4. Gets the size of the file and creates an {{jsxref("ArrayBuffer")}} to contain it. +5. Reads and writes to the file. +6. Persists the changes to disk and closes the synchronous access handle. - // Create a new directory handle. - const dirHandle = await root.getDirectoryHandle('New Folder', { create: true }); +```js +onmessage = async (e) => { + // Retrieve message sent to work from main script + const message = e.data; - // Recursively remove a directory. - await root.removeEntry('Old Stuff', { recursive: true }); + // Get handle to draft file + const root = await navigator.storage.getDirectory(); + const draftHandle = await root.getFileHandle('draft.txt', { create: true }); + // Get sync access handle + const accessHandle = await draftHandle.createSyncAccessHandle(); + + // Get size of the file. + const fileSize = accessHandle.getSize(); + // Read file content to a buffer. + const buffer = new DataView(new ArrayBuffer(fileSize)); + const readBuffer = accessHandle.read(buffer, { at: 0 }); + + // Write the message to the end of the file. + const encoder = new TextEncoder(); + const encodedMessage = encoder.encode(message); + const writeBuffer = accessHandle.write(encodedMessage, { at: readBuffer }); + + // Persist changes to disk. + accessHandle.flush(); + + // Always close FileSystemSyncAccessHandle if done. + accessHandle.close(); } ``` +> **Note:** In earlier versions of the spec, {{domxref("FileSystemSyncAccessHandle.close()", "close()")}}, {{domxref("FileSystemSyncAccessHandle.flush()", "flush()")}}, {{domxref("FileSystemSyncAccessHandle.getSize()", "getSize()")}}, and {{domxref("FileSystemSyncAccessHandle.truncate()", "truncate()")}} were wrongly specified as asynchronous methods. This has now been [amended](https://github.com/whatwg/fs/issues/7), but some browsers still support the asynchronous versions. + ## Specifications {{Specifications}}