opfs-utilities is a JavaScript package with utilities for working with the OPFS origin private file system.
This package isn't to a stable version yet. Please use it carefully.
opfs-utilities does not have any dependencies.
The goal of this package is to help web developers utilize the power of OPFS as quickly and easily as possible when their energy for learning is being spread thin.
For production, please consider writing your own custom OPFS utilities package that use the built-in methods and can be made to suit your particular needs.
Contributions are welcome! If you do something and think that the changes would be useful to everyone, please do submit a PR. Or fork your own thing and let me know about your discoveries.
https://github.com/grant-king/opfs-utils
:|:|:|::|:|:|::|:|:|::|:|:|::|:|:|::|:|:|::|:|:|::|:|:|:
:|:|:|::|:|:|::|:|:|::|:|:|::|:|:|::|:|:|::|:|:|::|:|:|:
npm install opfs-utilities
import {
get_opfs_info,
get_directory_handle,
get_file_handle,
store_text,
store_bytes,
copy_full_directory,
get_directory_contents_json,
} from 'opfs-utilities'
utils_demo()
async function utils_demo() {
// get_opfs_info
var info = await get_opfs_info()
console.log(info)
// get_directory_handle
const demo_dir_handle = await get_directory_handle(
["opfs_utils", "demo"]
)
console.log(demo_dir_handle)
// get_file_handle
const demo_file_handle = await get_file_handle(
["opfs_utils", "demo"], "demo.txt"
)
console.log(demo_file_handle)
// store_text
await store_text(demo_file_handle, "Hello OPFS")
// read text
const file_obj = await demo_file_handle.getFile()
const file_text = await file_obj.text()
console.log(file_text)
// store_bytes (accepts bytes or ArrayBuffer or blob)
const demo_file_handle_copy = await get_file_handle(
["opfs_utils", "demo"], "demo_copy.txt"
)
const demo_buffer = await demo_file.arrayBuffer()
await store_bytes(demo_file_handle_copy, demo_buffer)
// copy_full_directory
const demo_dir_handle_2 = await get_directory_handle(
["opfs_utils", "demo_2"]
)
await copy_full_directory(demo_dir_handle, demo_dir_handle_2)
// get_directory_contents_json
// get a JSON representation of full directory structure with File contents
const parent_dir_handle = await get_directory_handle(["opfs_utils"])
const dir_contents = await get_directory_contents_json(parent_dir_handle)
console.log(dir_contents)
// .remove
// recursively remove a directory
await parent_dir_handle.remove({recursive: true})
}:|:|:|::|:|:|::|:|:|::|:|:|::|:|:|::|:|:|::|:|:|::|:|:|:
:|:|:|::|:|:|::|:|:|::|:|:|::|:|:|::|:|:|::|:|:|::|:|:|:
The web's File System API extends device file management capabilities to the web browser. The OPFS is a powerful storage endpoint managed by the client's browser that is easily accessible through its low-level web APIs.
Here are some important characteristics of the OPFS:
-
Operations within the OPFS are fast and do not involve any user permissions.
-
The OPFS is private to the origin of the page where the interfaces are called.
-
The contents of this storage are not visible to the user.
-
The capacity is subject to browser storage quota restrictions.
-
The OPFS interfaces provide access to an extremely performant type of file.
To read more about the OPFS, see MDN's OPFS reference
You can utilize the power of the OPFS by employing a few built-in JavaScript methods.
navigator.storage.estimate()
// Log information about the origin's private browser storage usage
const storage_info = await navigator.storage.estimate()
console.log(storage_info)
// expected output:
// navigator.storage.getDirectory()
// log the OPFS root directory
const opfs_root = await navigator.storage.getDirectory()
console.log(opfs_root)
// expected output:
// ...getDirectoryHandle()
// log the handle for a new nested directory
const opfs_root = await navigator.storage.getDirectory()
current_handle = await opfs_root.getDirectoryHandle(
"demo", { create: true }
)
console.log(current_handle)
// expected output:
// ...getDirectoryHandle()(for a nested subdirectory)
// log the handle for a new double-nested directory
const directory_list = ['demo', 'subdirectory']
const opfs_root = await navigator.storage.getDirectory()
var current_handle = opfs_root
for (const directory_name of directory_list) {
current_handle = await current_handle.getDirectoryHandle(
directory_name, { create: true }
)
}
console.log(current_handle)
// expected output:
//
...getFileHandle()
// log the handle for a new file named demo_file.txt
const opfs_root = await navigator.storage.getDirectory()
const file_handle = await opfs_root.getFileHandle(
"demo_file.txt", { create: true }
)
console.log(file_handle)
// expected output:
//
...createWritable()and...getFile()
// write text to demo_file.txt in the OPFS root directory
// and log the file object
const opfs_root = await navigator.storage.getDirectory()
const file_handle = await opfs_root.getFileHandle(
"demo_file.txt", { create: true }
)
const text = "Hello OPFS"
const text_encoder = new TextEncoder()
const data_buffer = text_encoder.encode(text)
const file_writeable = await file_handle.createWritable()
await file_writeable.write(data_buffer)
await file_writeable.close()
const file = await file_handle.getFile()
console.log(file)
// expected output:
//
...createWritable()and...getFile()(to copy bytes)
// copy demo_file.txt to demo_file_2.txt in the OPFS root directory
// and then log the directory values
const opfs_root = await navigator.storage.getDirectory()
const file_handle_1 = await opfs_root.getFileHandle(
"demo_file.txt", { create: true }
)
const file_handle_2 = await opfs_root.getFileHandle(
"demo_file_copy.txt", { create: true }
)
const text = "Hello OPFS"
const text_encoder = new TextEncoder()
const data_buffer = text_encoder.encode(text)
const file_writeable_1 = await file_handle.createWritable()
await file_writeable_1.write(data_buffer)
await file_writeable_1.close()
const file_1 = await file_handle_1.getFile()
const file_writeable_2 = await file_handle_2.createWritable()
await file_writeable_2.write(await file_1.arrayBuffer())
await file_writeable_2.close()
console.log(await opfs_root.values())
// expected output:
//
:|:|:|::|:|:|::|:|:|::|:|:|::|:|:|::|:|:|::|:|:|::|:|:|:
:|:|:|::|:|:|::|:|:|::|:|:|::|:|:|::|:|:|::|:|:|::|:|:|:
opfs-utilities package includes the following functions that compose the built-in OPFS methods shown above.
-
get_opfs_info
-
get_directory_handle
-
get_file_handle
-
store_text
-
store_bytes
-
get_directory_contents_json
-
copy_full_directory
:: get storage info in a flat object with descriptive keys
async function get_opfs_info()
=>
{
"storage_total": quota,
"storage_used": usage,
"usage_cache": usageDetails.caches,
"usage_filesystem": usageDetails.fileSystem,
}:: get a FileSystemDirectoryHandle object using a list of directory name strings
async function get_directory_handle(
directory_list=["dirname", "subdir"]
)
=>
FileSystemDirectoryHandle:: get a FileSystemFileHandle object using a list of directory name strings and a file name string
async function get_file_handle(
directory_list=["for", "example"],
filename="ie.txt"
)
=>
FileSystemFileHandle:: store text using a FileSystemFileHandle object and a string of text
async function store_text(
file_handle=FileSystemFileHandle,
text="Hello text"
)
=>
none:: store text using a FileSystemFileHandle object and an ArrayBuffer or Uint8Array
async function store_bytes(
file_handle=FileSystemFileHandle,
bytes=ArrayBuffer||Uint8Array,
)
=>
none:: get a JSON representation containing directory names and nested file names with their File objects that are stored within a directory given its FileSystemDirectoryHandle
async function get_directory_contents_json(
directory_handle=FileSystemDirectoryHandle
)
=>
{
"file_name_1": File object,
"directory_name_I": {
"file_name_2": File object,
"file_name_3": File object,
},
"directory_name_II": {
"file_name_4": File object,
"subdirectory": {
"file_name_5": File object,
"file_name_6": File object,
},
},
}:: recursively copy the contents of a source directory to an output directory, given a FileSystemDirectoryHandle for each directory.
async function copy_full_directory(
source_dir_handle=FileSystemDirectoryHandle,
output_dir_handle=FileSystemDirectoryHandle,
)
=>
none