Gathering detailed insights and metrics for file-system-access
Gathering detailed insights and metrics for file-system-access
Gathering detailed insights and metrics for file-system-access
Gathering detailed insights and metrics for file-system-access
File System Access API implementation (ponyfill) with pluggable storage adapters via IndexedDB, Cache API, in-memory etc.
npm install file-system-access
Typescript
Module System
Min. Node Version
Node Version
NPM Version
TypeScript (51.21%)
JavaScript (44.39%)
HTML (4.4%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
MIT License
24 Stars
76 Commits
1 Forks
2 Branches
1 Contributors
Updated on Jun 26, 2025
Latest Version
1.0.4
Package Id
file-system-access@1.0.4
Unpacked Size
471.91 kB
Size
87.27 kB
File Count
94
NPM Version
6.14.12
Node Version
14.16.1
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
6
1
This is an implementation of the File System Access specification. It is a ponyfill that uses the native browser implementation when available and falls back to a custom one otherwise. It also includes several storage adapters which can be used in the browser, but also in other environments, such as NodeJS or Deno.
The library roughly contains the following:
showDirectoryPicker
, showOpenFilePicker
and showSaveFilePicker
, with fallbacks to regular input elements.FileSystemFileHandle
and FileSystemDirectoryHandle
interfaces.FileSystemWritableFileStream
to truncate and write data.navigator.storage.getDirectory()
(getOriginPrivateDirectory
) which can read & write data to and from several sources called adapters, not just the browser sandboxed file systemDataTransferItem.prototype.getAsFileSystemHandle()
This package builds upon native-file-system-adapter, adding several bug fixes, updates for compliance with the latest spec, browser support improvements (especially Safari), support for bundlers, stricter error handling and more. It is fully rewritten in TypeScript and provides type-safe declarations out-of-the-box.
When getOriginPrivateDirectory
is called with no arguments, the browser's native sandboxed file system is used, just like calling navigator.storage.getDirectory()
.
Optionally, a file system backend adapter can be provided as an argument. This ponyfill ships with a few backends built in:
node
: Uses NodeJS's fs
moduledeno
: Interact with filesystem using Denosandbox
(deprecated): Uses requestFileSystem. Only supported in Chromium-based browsers using the Blink
engine.indexeddb
: Stores files into the browser's IndexedDB
object database.memory
: Stores files in-memory. Thus, it is a temporary file store that clears when the user navigates away.cache
: Stores files with the browser's Cache API in request/response pairs.You can even load in your own underlying adapter and get the same set of API's by implementing the FileSystemFileHandleAdapter and FileSystemFolderHandleAdapter interfaces
The API is designed in such a way that it can work with or without the ponyfill if you choose to remove or add this.
It's not trying to interfere with the changing spec by using other properties that may conflict with the feature changes to the spec.
You can directly import the module using an absolute URL:
1<script type="module">
2import { getOriginPrivateDirectory } from 'https://cdn.jsdelivr.net/npm/file-system-access/lib/es2018.js'
3
4// Get a directory handle for a sandboxed virtual file system
5// same as calling navigator.storage.getDirectory()
6const dirHandle1 = await getOriginPrivateDirectory()
7
8// or use an adapter (see adapters table above for a list of available adapters)
9const dirHandle2 = await getOriginPrivateDirectory(import('https://cdn.jsdelivr.net/npm/file-system-access/lib/adapters/<adapterName>.js'))
10</script>
Works in Node.JS v14.8+ or in the browser, with a module bundler such as Webpack.
npm i file-system-access
1import { getOriginPrivateDirectory } from 'file-system-access' 2import indexedDbAdapter from 'file-system-access/lib/adapters/indexeddb.js' 3import nodeAdapter from 'file-system-access/lib/adapters/node.js' 4 5const dirHandle = await getOriginPrivateDirectory(indexedDbAdapter) 6const nodeDirHandle = await getOriginPrivateDirectory(nodeAdapter, './real-dir')
You can get a directory handle to a sandboxed virtual file system using the getOriginPrivateDirectory
function.
This is a legacy name introduced by an older Native File System
specification and is kept for simplicity.
It is equivalent to the navigator.storage.getDirectory()
method introduced by the later File System Access spec.
1import { getOriginPrivateDirectory, support } from 'file-system-access'
2
3// Uses only native implementation - same as calling navigator.storage.getDirectory()
4if (support.adapter.native) {
5 handle = await getOriginPrivateDirectory()
6}
7// Blinks old sandboxed api
8if (support.adapter.sandbox) {
9 handle = await getOriginPrivateDirectory(import('file-system-access/lib/adapters/sandbox.js'))
10}
11// fast in-memory file system
12handle = await getOriginPrivateDirectory(import('file-system-access/lib/adapters/memory.js'))
13// Using indexDB
14handle = await getOriginPrivateDirectory(import('file-system-access/lib/adapters/indexeddb.js'))
15// Store things in the new Cache API as request/responses (bad at mutating data)
16if (support.adapter.cache) {
17 handle = await getOriginPrivateDirectory(import('file-system-access/lib/adapters/cache.js'))
18}
19
20// Node only variant:
21handle = await getOriginPrivateDirectory(import('file-system-access/lib/adapters/memory.js'))
22handle = await getOriginPrivateDirectory(import('file-system-access/lib/adapters/node.js'), './starting-path')
23
24// Deno only variant:
25handle = await getOriginPrivateDirectory(import('file-system-access/src/adapters/memory.js'))
26handle = await getOriginPrivateDirectory(import('file-system-access/src/adapters/deno.js'), './starting-path')
1import { showDirectoryPicker, showOpenFilePicker } from 'file-system-access' 2 3// The polyfilled (file input) version will turn into a memory adapter 4// You will have read & write permission on the memory adapter, 5// you might want to transfer (copy) the handle to another adapter 6const [fileHandle] = await showOpenFilePicker({_preferPolyfill: boolean, ...sameOpts}) 7const dirHandle = await showDirectoryPicker({_preferPolyfill: boolean, ...sameOpts})
1// Apply polyfill for DataTransferItem.prototype.getAsFileSystemHandle() 2 3import { polyfillDataTransferItem } from 'file-system-access' 4await polyfillDataTransferItem(); 5 6// or just use a static import 7 8import 'file-system-access/lib/polyfillDataTransferItem.js' 9 10window.ondrop = async evt => { 11 evt.preventDefault() 12 for (let item of evt.dataTransfer.items) { 13 const handle = await item.getAsFileSystemHandle() 14 console.log(handle) 15 } 16}
1import { showOpenFilePicker, getOriginPrivateDirectory } from 'file-system-access' 2 3// request user to select a file 4const [fileHandle] = await showOpenFilePicker({ 5 types: [], // default 6 multiple: false, // default 7 excludeAcceptAllOption: false, // default 8 _preferPolyfill: false // default 9}) 10 11// returns a File Instance 12const file = await fileHandle.getFile() 13 14// copy the file over to a another place 15const rootHandle = await getOriginPrivateDirectory() 16const fileHandle = await rootHandle.getFileHandle(file.name, { create: true }) 17const writable = await fileHandle.createWritable() 18await writable.write(file) 19await writable.close()
1import { showSaveFilePicker } from 'file-system-access' 2 3const fileHandle = await showSaveFilePicker({ 4 _preferPolyfill: false, 5 suggestedName: 'Untitled.png', 6 types: [ 7 { accept: { "image/png": [ ".png" ] } }, 8 { accept: { "image/jpg": [ ".jpg" ] } }, 9 { accept: { "image/webp": [ ".webp" ] } } 10 ], 11 excludeAcceptAllOption: false // default 12}) 13 14// Look at what extension they have chosen 15const extensionChosen = fileHandle.name.split('.').pop() 16 17const blob = { 18 jpg: generateCanvasBlob({ type: 'blob', format: 'jpg' }), 19 png: generateCanvasBlob({ type: 'blob', format: 'png' }), 20 webp: generateCanvasBlob({ type: 'blob', format: 'webp' }) 21}[extensionChosen] 22 23await blob.stream().pipeTo(fileHandle.createWritable()) 24// or 25var writer = fileHandle.getWritable() 26await writer.write(blob) 27await writer.close()
When importing as an ES module, browsers that support dynamic imports and ES2018 features are a minimum requirement. When using a bundler, this restriction is no longer applicable.
When the directory picker falls back to input
elements, the browser must support webkitdirectory and webkitRelativePath. Because of this, support for picking directories is generally poor on Mobile browsers.
For drag and drop, the getAsFileSystemHandle()
polyfill depends on the File and Directory Entries API
support, more specifically FileSystemDirectoryEntry, FileSystemFileEntry and webkitGetAsEntry.
showDirectoryPicker
and showOpenFilePicker
will not throw any AbortError
s (e.g. user cancellations) when using a fallback input elementshowDirectoryPicker
will return a flat hierarchy when a fallback input
element is used and webkitRelativePath
is not supported (e.g. mobile Safari). This can be detected by checking if the name
attribute of the root directory handle is an empty string.showSaveFilePicker
may not actually show any prompt when using a fallback input (e.g. on Chrome the file is auto-saved to the browser's preferred download folder)Saving/downloading a file is borrowing some of ideas from StreamSaver.js. The difference is:
to set up a service worker you have to basically copy the example and register it:
1navigator.serviceWorker.register('sw.js')
Without service worker you are going to write all data to the memory and download it once it closes.
Seeking and truncating won't do anything. You should be writing all data in sequential order when using the polyfilled version.
npx http-server -p 3000 .
http://localhost:3000/example/test.html
in your browser.npm run test-node
npm run test-deno
I recommend to follow up on this links for you to learn more about the API and how it works
getSystemDirectory
).file-system-access is licensed under the MIT License. See LICENSE
for details.
No vulnerabilities found.
No security vulnerabilities found.