If you’re like most people, you probably have a file system on your computer. It’s where you store your photos, music, and videos. It’s also where you store your documents and files that you use to work on the web. But if you’re using a web browser, there’s a good chance that your file system is not accessible. That’s because the web browser doesn’t understand how to access file systems on other computers. Fortunately, there are ways to get around this problem. You can use a web app to access your file system, or you can use a software program that does this for you. either way, it’s an easy way to keep your files safe and accessible. There are many web apps that offer this feature. For example, Google Drive is a great choice because it offers many features for accessing your file system. You can create folders and add files to them easily, and then access them from any computer in the world without having to worry about permissions or security issues. Another great option is iCloud Drive. This app allows you to access all of your files from any device in the world without having to remember multiple addresses for each file! Just enter the name of the document or folder you want to access into the app’s search bar, and then click “add.” You’ll be able to see all of the files in that document or folder right away!
What’s now the File System Access API used to be known as the Native File System API. It’s had a long development involving several rounds of iteration to address security concerns. The feature was turned on in the stable release of Chrome 86.
Overview
File support on the web has historically been limited to selecting a file from your device using
. It’s impossible to write directly to the user’s filesystem using previous APIs. You have to use download links if you need to provide a file to the user.
The File System Access API provides a way for websites to attain read-write access to your device’s filesystem. This makes it possible to create new classes of complex web apps that interact with your files. Web-based text editors, photo libraries and media players could all load content stored locally on your device.
Using the API, you can enumerate the contents of directories, read data from files and write back to new and existing files stored on the user’s device. Access is provided via the FileSystemFileHandle and FileSystemDirectoryHandle handle objects, which represent files on the user’s system.
The File System Access API can only be used from pages loaded over HTTPS. It’s gated behind permissions which the user must explicitly consent to. The user will be prompted to provide consent each time you use the API. This uses the same system as permission requests for other web features, such as notifications and camera access.
Like most modern JavaScript APIs, File System Access is asynchronous. Calls to its API surface return Promises. The cleanest way to consume it is via the async/await syntax of ES7, which is what we’ll use in the following examples.
Reading a File
To read a file, you open a file picker using the window.showOpenFilePicker() function. There’s no need to use the HTML
element.
The user’s operating system will render a native file picker. Once the user selects a file, the returned Promise will resolve with an array of FileSystemFileHandle objects.
To get the contents of the file, call the getFile() method of the file handle. This returns a File object, which is what you get when working with an HTML filepicker. Once you have the File, you can use its blob methods such as text() and stream() to read its data.
window.showOpenFilePicker() accepts an options object as its sole parameter. You can allow the user to select multiple files by setting the multiple option. To restrict the user to specific file types, pass the types option with an array of objects describing the allowed types. Each type object should contain description and accept properties which determine the type’s file picker label and permissible MIME types respectively.
An “all files” option is usually shown as a permissible file type, even when the types option is set. You can disable the all files override by setting the excludeAcceptAllOption option.
Writing to a File
Once you have a file handle, you can also write to it! There’s another abstraction layer to contend with as you must first acquire a FileSystemWritableFileStream. This stream represents the file and allows you to keep writes in-memory until they’re persisted to the disk.
Here’s how to replace the contents of a file handle obtained from showOpenFilePicker():
Calling write() on a writable stream will insert text at the current cursor position in the stream. To change the position of the cursor, call the seek() method passing the new cursor position. A third method on writable streams is truncate(), which resizes the file down to a maximum size in bytes which you must specify.
Sometimes you’ll need to write to a new file. You can do this by asking the user to pick a new location for the file using window.showSaveFilePicker(). This works similarly to window.showOpenFilePicker() – it returns a FileHandle which you’ll then be able to call createWritable() on to get a writable stream.
You can use the excludeAcceptAllOption and types options with window.showSaveFilePicker(). They work identically to their showOpenFilePicker() counterparts.
Directories
The File System Access API also exposes directories. The user can be prompted to select a directory using window.showDirectoryPicker(). This function accepts no parameters. It returns a promise which will resolve with a FileSystemDirectoryHandle representing the directory.
You can enumerate the contents of the directory by iterating over its values(). The values will be either file or directory handle instances.
If you know the name of the file or subdirectory you’re looking for, you can use the getFileHandle() or getDirectoryHandle() methods to retrieve it. These methods both accept an options object which currently has a single property, create. Setting this to true will cause the requested file or directory to be automatically created within the filesystem if it doesn’t already exist.
You can delete files and folders from a directory using the removeEntry() method on a directory handle. This accepts the relative name of the file or subdirectory to delete. When deleting a directory, you may optionally set the recursive option to also remove its contents.
Permissions
Permissions for the File System Access API are split into read and write components. Browers will usually show a separate permission prompt for both read and write and for each file or directory you access.
Once you’ve acquired permission, you can use the file or directory handle for as long as your site remains open. An exception is if the underlying resource gets changed or modified on disk, in which case the handle is invalidated.
You can check whether you still have permission to use a handle by calling its queryPermission() method:
When you need to re-request permission, use the requestPermission() method in the same manner.
You should avoid prompting for permission too often or for too many files. This is likely to create a poor user experience due to multiple successive dialogs appearing. Always prompt for permission in response to an explicit user action such as clicking a button.
The API makes no provision for persistent permission grants. Once all tabs for your site have been closed, any granted file permissions will be revoked.
Conclusion
The File System Access API is one of the most exciting browser APIs to have launched in recent months. It has the potential to transform the capabilities of web applications, making them an even more viable alternative to desktop programs.
Whether you’re building a text editor, photo gallery or enterprise line-of-business app, being able to interact with the device’s filesystem gives you new possibilities. Although browser support will be limited to Chrome and Opera for the foreeseable future (Mozilla views the API as “potentially very dangerous”), File System Access helps evolve the web as an application platform and further reduces the gap between the web and native apps.