*** title: Storage description: >- Upload, download, and browse files in workspace storage — screenshots, downloads, exports. ------------------- Storage gives workspaces a place to save and retrieve files — screenshots, downloads, CSV exports, PDFs. Each workspace can have its own storage namespace, and multiple workspaces can share one. Access via `bctrl.storage(workspaceName)`. ```ts const storage = bctrl.storage("my-workspace"); ``` ## upload(filePath, data, filename?) Upload a file to workspace storage. ```ts await storage.upload("exports/report.csv", csvBuffer); // With explicit filename await storage.upload("exports/report.csv", csvBuffer, "q1-report.csv"); ``` | Parameter | Type | Required | Description | | ---------- | ------------------------------ | -------- | ------------------------------------------------------------ | | `filePath` | `string` | Yes | Logical path in storage (e.g., `exports/report.csv`) | | `data` | `Buffer \| Uint8Array \| Blob` | Yes | File content | | `filename` | `string` | No | Override the filename (defaults to last segment of filePath) | **Returns** `UploadResult` *** ## uploadObject(data, options?) Upload a file and register it in the object catalog. Use this when you want storage objects to be queryable by source, runtime, driver, etc. ```ts await storage.uploadObject(screenshotBuffer, { source: "screenshot", runtimeId: "browser-1", filename: "homepage.png", }); ``` | Parameter | Type | Required | Description | | ------------------- | ------------------------------ | -------- | -------------------------------------------------- | | `data` | `Buffer \| Uint8Array \| Blob` | Yes | File content | | `options.source` | `string` | No | Source identifier (e.g., `screenshot`, `download`) | | `options.runtimeId` | `string` | No | Associated runtime ID | | `options.driver` | `string` | No | Driver that produced this object | | `options.filename` | `string` | No | Filename | **Returns** `UploadObjectResult` *** ## get(filePath) Download a file as raw bytes. ```ts const data = await storage.get("exports/report.csv"); ``` | Parameter | Type | Required | Description | | ---------- | -------- | -------- | ----------------------- | | `filePath` | `string` | Yes | Logical path in storage | **Returns** `Buffer` *** ## getDownloadUrl(filePath) Get a presigned URL for direct download. ```ts const url = await storage.getDownloadUrl("exports/report.csv"); ``` | Parameter | Type | Required | Description | | ---------- | -------- | -------- | ----------------------- | | `filePath` | `string` | Yes | Logical path in storage | **Returns** `string` — presigned download URL. *** ## browse(options?) Browse files and folders with hierarchical listing. ```ts const result = await storage.browse({ prefix: "exports/", limit: 50 }); for (const file of result.files) { console.log(file.path, file.size); } ``` | Parameter | Type | Required | Description | | --------- | -------- | -------- | --------------------- | | `prefix` | `string` | No | Path prefix to filter | | `cursor` | `string` | No | Pagination cursor | | `limit` | `number` | No | Max results | **Returns** `StorageBrowseResult` *** ## read(filePath, maxBytes?) Read a UTF-8 text preview of a file. ```ts const result = await storage.read("exports/report.csv", 1024); console.log(result.content); ``` | Parameter | Type | Required | Description | | ---------- | -------- | -------- | ----------------- | | `filePath` | `string` | Yes | Logical path | | `maxBytes` | `number` | No | Max bytes to read | **Returns** `StorageReadResult` *** ## listObjects(options?) List objects from the storage catalog with metadata filters. ```ts const objects = await storage.listObjects({ source: "screenshot", runtimeId: "browser-1", }); ``` | Parameter | Type | Required | Description | | ------------ | -------- | -------- | --------------------- | | `source` | `string` | No | Filter by source | | `runtimeId` | `string` | No | Filter by runtime | | `driver` | `string` | No | Filter by driver | | `pathPrefix` | `string` | No | Filter by path prefix | | `limit` | `number` | No | Max results | | `offset` | `number` | No | Skip first N results | **Returns** `StorageObject[]` *** ## downloadObject(id) Download an object by its catalog ID. ```ts const data = await storage.downloadObject("obj_abc123"); ``` **Returns** `Buffer` *** ## getObjectDownloadUrl(id) Get a presigned URL for an object by catalog ID. ```ts const url = await storage.getObjectDownloadUrl("obj_abc123"); ``` **Returns** `string` *** ## getDownloadsZip() Download all files as a single ZIP archive. ```ts const zip = await storage.getDownloadsZip(); ``` **Returns** `Buffer` — ZIP file content. *** ## delete(filePath) Delete a file by logical path. ```ts await storage.delete("exports/report.csv"); ``` *** ## deleteObject(id) Delete an object by catalog ID. ```ts await storage.deleteObject("obj_abc123"); ``` *** ## deleteAll() Delete all files in this workspace's storage. ```ts const count = await storage.deleteAll(); console.log(`Deleted ${count} files`); ``` **Returns** `number` — count of deleted files. *** ## forWorkspace(workspace) Create a client for a different workspace namespace, preserving the same auth. ```ts const otherStorage = storage.forWorkspace("other-workspace"); ``` **Returns** `StorageClient` *** ## Usage with workspaces Storage is mounted to workspaces via the `storage` mount. See [Scopes & Inheritance](/sdk/concepts/scopes-and-inheritance). ```ts const workspace = await bctrl.workspaces.create({ name: "data-pipeline", mounts: { storage: { workspace: "shared-exports" }, }, }); ```