DOCS · GUIDE

The virtual file system

“Where did my output go?” is the most-asked question in the issue tracker. Short answer: into a virtual filesystem you control. This page is the long answer.

The model

In a browser there is no real disk, so GDAL reads and writes a virtual filesystem. You decide which backing store a path uses: /opfs/… persists in the Origin Private File System, /vsimem/… lives in memory, and GDAL's own VSI prefixes (/vsizip/ & co.) layer on top of either. On Node and React Native there's no indirection: paths are host paths.

OPFS: persistent, big-file friendly

write in, read back
const Module = await initCppJs({ useWorker: true, fs: { opfs: true } });

// in: standard web API writes into OPFS
const dir = await navigator.storage.getDirectory();
const fh  = await dir.getFileHandle("input.tif", { create: true });
const ws  = await fh.createWritable(); await ws.write(file); await ws.close();

// gdal sees it as /opfs/input.tif
const ds  = await Gdal.open("/opfs/input.tif");
const out = await ds.translate("/opfs/out.tif", opts);
await out.close();

// out: read the result back with the same web API
const outHandle = await dir.getFileHandle("out.tif");
const blob = await outHandle.getFile();   // → download, upload, display

OPFS survives page reloads and handles multi-gigabyte files. It's the right default for user-supplied data.

In-memory: /vsimem/

bytes in, no storage
const bytes = new Uint8Array(await file.arrayBuffer());
await Gdal.fileFromMemBuffer("/vsimem/in.geojson", bytes);
const ds = await Gdal.open("/vsimem/in.geojson");
// … later
await Gdal.unlink("/vsimem/in.geojson");

Fast and ephemeral, but the whole file occupies wasm memory. Prefer OPFS beyond a few hundred megabytes (see memory).

Zipped data: /vsizip/ and friends

zipped shapefile, no unzipping
const ds = await Gdal.open("/vsizip//opfs/districts.zip");

GDAL's chained VSI handlers work on any backing path: read inside archives with /vsizip/, and discover what a multi-dataset file contains with Gdal.getSubdatasetInfo(path). Available prefixes on your build: Gdal.getFileSystemsPrefixes().

FS management API

CALLPURPOSE
Gdal.readDir(dir) / readDirRecursive(dir)List entries
Gdal.mkdir(dir, mode) / mkdirRecursive(dir, mode)Create directories (or Module.FS.mkdirTree(dir))
Gdal.unlink(path) / unlinkBatch(paths)Delete files
Gdal.rmdir(dir) / rmdirRecursive(dir)Delete directories
Gdal.rename(from, to) · Gdal.copyFile(to, from)Move / copy
Gdal.fileFromMemBuffer(path, bytes)Create a /vsimem file from bytes
ds.getFileList()All files belonging to a dataset (Shapefile = .shp + .shx + .dbf …)
Module.getFileList(dir)Outputs in a directory, with sizes
SHAPEFILE NOTE One conversion can produce several files. Collect them with ds.getFileList() instead of assuming a single path: the v2 era's issue #45, solved structurally.

Network sources: not yet

/vsicurl/, /vsis3/ and WMS/WFS need an HTTP client inside the wasm build; that work is tracked in issue #67. Today: fetch() the bytes yourself and hand them to GDAL via OPFS or /vsimem/.