This module allows you to easily use the
Native File System API on supporting browsers,
with a transparent fallback to the <input type="file">
and <a download>
legacy methods.
Read more on the background of this module in my post Progressive Enhancement In the Age of Fugu APIs.
See the library in action: https://browser-nativefs.glitch.me/.
The module feature-detects support for the Native File System API and only loads the actually relevant code.
// The imported methods will use the Native
// File System API or a fallback implementation.
import {
fileOpen,
directoryOpen,
fileSave,
} from 'https://unpkg.com/browser-nativefs';
(async () => {
// Open a file.
const blob = await fileOpen({
mimeTypes: ['image/*'],
});
// Open multiple files.
const blobs = await fileOpen({
mimeTypes: ['image/*'],
multiple: true,
});
// Open all files in a directory,
// recursively including subdirectories.
const blobsInDirectory = await directoryOpen({
recursive: true
});
// Save a file.
await fileSave(blob, {
fileName: 'Untitled.png',
});
})();
// Options are optional.
const options = {
// List of allowed MIME types, defaults to `*/*`.
mimeTypes: ['image/*'],
// List of allowed file extensions, defaults to `''`.
extensions: ['png', 'jpg', 'jpeg', 'webp'],
// Set to `true` for allowing multiple files, defaults to `false`.
multiple: true,
// Textual description for file dialog , defaults to `''`.
description: 'Image files',
};
const blobs = await fileOpen(options);
Note that there are some differences between the Native File System API
and the fallback approach
<input type="file" webkitdirectory multiple>
.
Namely, the Native File System API currently doesn't provide useful
relative path info as
webkitRelativePath
did, so you need to keep track of paths yourself.
// Options are optional.
const options = {
// Set to `true` for allowing multiple directories, defaults to `false`.
multiple: true,
// Set to `true` to recursively open files in all subdirectories,
// defaults to `false`.
recursive: true,
};
const blobs = await directoryOpen(options);
// Options are optional.
const options = {
// Suggested file name to use, defaults to `''`.
fileName: 'Untitled.txt',
};
// Optional file handle to save back to an existing file.
// This will only work with the Native File System API.
// Get a `FileHandle` from the `handle` property of the `Blob`
// you receive from `fileOpen()` (this is non-standard).
const handle = previouslyOpenedBlob.handle;
await fileSave(someBlob, options, handle);
You can see the module in action in the Excalidraw drawing app.
A similar, but more extensive library called native-file-system-adapter is provided by @jimmywarting.
Thanks to @developit for improving the dynamic module loading and @dwelle for the helpful feedback and issue reports. The TypeScript type annotations were provided by @nanaian.
Apache 2.0.
This is not an official Google product.