只读kind可用于区分文件与目录的固定标记。
只读mode当前代理及其派生项被授予的访问模式。
只读name目录 basename,不包含父目录或真实路径。
确保目录存在并返回同一个代理。
可选options: CreateOptions可选的父目录创建与目标独占创建设置。省略时等同于
{ recursive: false, exclusive: false };完整语义见 CreateOptions。
Host 确认目录存在后返回当前同一个 DirectoryHandle proxy;成功后
result === directory。不会创建新的授权 handle,也不会刷新或改变代理的 name、mode。
HbMiniProgramSDKError options 非对象,或 recursive / exclusive 不是 boolean 时
返回 INVALID_PARAMS;代理不是 readwrite 时在发送 bridge 请求前返回 FILE_ACCESS_DENIED。
HbMiniProgramSDKError 当前运行快照缺少或未启用 filesystem 时返回
PERMISSION_NOT_IN_SNAPSHOT / PERMISSION_DENIED;Host 未开放或未协商到 directory.create 时返回
METHOD_FORBIDDEN,旧 Runtime 可返回 METHOD_NOT_FOUND。
HbMiniProgramSDKError recursive: false 且任一父目录缺失时返回
DIRECTORY_NOT_FOUND;目标实际是文件或路径中的祖先实际是文件时返回 FILE_TYPE_MISMATCH;
exclusive: true 且目录已存在时返回 DIRECTORY_ALREADY_EXISTS。
HbMiniProgramSDKError 外部 direct handle 已失效、伪造或不属于当前 Runtime session
时返回 FILE_ACCESS_REVOKED;Host 创建失败或底层平台 I/O 失败时返回相应稳定文件错误码,
无法识别的 Host 错误统一为 FILE_IO_FAILED。SDK / Runtime 终止或请求超时还可能返回
SDK_DESTROYED、RUNTIME_DESTROYED、RUNTIME_UNAVAILABLE 或 REQUEST_TIMEOUT。
目标缺失时创建空目录。recursive: true 会在当前逻辑 root 内同时创建缺失父目录;它不会允许
..、绝对路径或越过 sandbox / 用户选择目录的授权边界。目标已是目录时,默认调用作为幂等的
ensure-exists 成功,不删除、清空或重新创建其中内容;需要检测最终目标冲突时传
exclusive: true。exclusive 只约束最终目录,recursive 创建的父目录可以已经存在。
若同一位置实际是文件,则不会把文件替换为目录。
调用要求当前代理的 mode === 'readwrite'。sandbox 目录固定继承 readwrite;从
files.pickDirectory({ mode: 'readwrite' }) 返回的外部目录派生后代时也可在该授权范围内创建,
但默认 read 的选择结果及其后代会在本地 mode 检查时拒绝。创建不会扩大授权到所选目录之外,
也不会让外部目录获得 remove() 权限;外部 direct handle 及其后代仍只在当前 Runtime session
有效。Runtime 会重新校验 direct handle 的 provenance,Host 还会绑定当前 Mini-program identity。
该方法要求 package.json#heybox.permissions 已声明并启用 filesystem,但不要求新的可信用户
手势;只有最初调用 pickDirectory() 取得外部授权时需要用户操作。它不占用新的外部 direct-handle
配额,也不暴露 Host 真实路径。
新 PC Host 支持该 operation;Android / iOS 需要 1.3.396+ 并以 system.describe 实际宣告的
operation 集为准,OHOS 同样按 Host 协商结果启用。Web、Browser Dev Host、旧 Host 或 operation
集不完整时 fail closed,不提供浏览器文件系统、OPFS 或内存 fallback。
创建目录后,可用当前代理的 file() / directory()
同步派生后代代理,并用 list() 枚举直接子项;派生与枚举结果继承
当前目录的 mode。若最终目标应是文件,使用 FileHandle.create;它复用同一组
recursive / exclusive 选项,但独占冲突返回 FILE_ALREADY_EXISTS。
import hbSDK, { HbMiniProgramSDKError } from '@heybox/hb-sdk'
const reports = hbSDK.files.sandbox.directory('exports/2026')
const sameReports = await reports.create({ recursive: true })
console.assert(sameReports === reports)
const summary = reports.file('summary.json')
await summary.create()
await summary.writeText('{"ready":true}')
console.log((await reports.list()).map(entry => entry.name))
try {
await reports.create({ exclusive: true })
} catch (error) {
if (!(error instanceof HbMiniProgramSDKError) || error.code !== 'DIRECTORY_ALREADY_EXISTS') throw error
}
按规范相对路径派生目录代理。
相对于当前逻辑根、使用 / 分隔的规范路径。必须是非空字符串,不能以
/ 开头或结尾,不能包含空 segment、反斜杠、NUL 或其他控制字符。. 是仅有的特例:只有
整个参数等于 '.' 时才表示当前逻辑根;./cache、cache/.、cache/../secret 等含点段路径
不会被折叠或解析,而会直接拒绝。
当前 SDK session 内延迟访问目标目录的冻结
DirectoryHandle。其 kind 固定为
'directory',name 是末段 basename(传 '.' 时为 '.'),mode 继承当前逻辑根;因此
files.sandbox.directory() 返回 readwrite,从用户选择目录继续派生时则继承所选目录的
read 或 readwrite,不能通过子路径提升权限。
HbMiniProgramSDKError
relativePath 不是字符串、为空、以 / 开头或结尾,包含连续 /、任何 . / .. 点段、
反斜杠或控制字符时,同步抛出 INVALID_PARAMS;完整参数 '.' 除外。
该方法同步校验路径并创建 lazy proxy,不检查目录是否存在或创建目录,不执行文件 I/O,不发送
bridge 请求,也不会打开系统选择器。调用本身因此不需要用户手势,不会触发 Host operation,
不会占用 picker / saveFile() 的 direct handle 配额,也不会暴露宿主真实路径。
后续 I/O 才要求在 package.json#heybox.permissions 中声明并启用 filesystem,并由 Host 开放
对应 operation:DirectoryHandle 的 create()、
exists()、list()、remove() 分别使用 directory.create、directory.exists、
directory.list、directory.remove。当前运行快照缺少或未启用所需权限时分别返回
PERMISSION_NOT_IN_SNAPSHOT 或 PERMISSION_DENIED,Host 未开放具体 operation 时返回
METHOD_FORBIDDEN;这些错误在调用异步方法时发生,不由本方法抛出。
files.sandbox.directory('.') 是沙箱根目录的逻辑代理,可用于 exists() 或 list(),但不能删除;
对它调用 remove() 会返回 FILE_ACCESS_DENIED。普通子目录代理只表达目标位置:需要确保目录
存在时调用 create(),需要观察直接子项时调用 list()。若目标是文件,使用
files.sandbox.file();若要访问用户选择的外部目录,使用
files.pickDirectory()。
import hbSDK from '@heybox/hb-sdk'
// 构造代理时没有 I/O;父目录也不会被隐式创建。
const reports = hbSDK.files.sandbox.directory('reports/2026')
console.log(reports.kind, reports.name, reports.mode)
// directory, 2026, readwrite
await reports.create({ recursive: true })
// `.` 只作为完整参数表示沙箱根;它不是可嵌入路径的点段。
const root = hbSDK.files.sandbox.directory('.')
const entries = await root.list({ limit: 100 })
console.log(entries.map(entry => entry.name))
create()、exists()、list() 与 remove()。检查目录是否存在。
Runtime 对当前目录引用执行一次 Host stat 后得到的 boolean 快照。目标目录存在且 Host
确认为目录时返回 true;目标或任一祖先不存在,目标实际是文件,或 Host 以
FILE_NOT_FOUND、DIRECTORY_NOT_FOUND、FILE_TYPE_MISMATCH 报告同类状态时返回 false;Host
stat 响应不是对象或 kind 不是 'directory' 时也按类型不匹配返回 false。不返回目录元数据、
句柄或缺失原因。
HbMiniProgramSDKError 当前运行快照缺少或未启用 filesystem 时返回
PERMISSION_NOT_IN_SNAPSHOT / PERMISSION_DENIED;Host 未开放或未协商到 directory.exists
(底层要求 files.stat)时返回 METHOD_FORBIDDEN,旧 Runtime 可返回 METHOD_NOT_FOUND。
HbMiniProgramSDKError 外部 direct directory handle 被撤销、不属于当前或已结束的
Runtime session 时返回 FILE_ACCESS_REVOKED;Host 拒绝当前目录授权时返回 FILE_ACCESS_DENIED。
这些授权错误不会被转换为 false。
HbMiniProgramSDKError Host 返回未归类的错误、公开 bridge 返回非 boolean 结果或底层
I/O 失败时返回 FILE_IO_FAILED 或对应稳定文件错误码。握手失败、SDK / Runtime 已终止或不可用、
调用超时时还可能返回 HANDSHAKE_FAILED、SDK_DESTROYED、RUNTIME_DESTROYED、
RUNTIME_UNAVAILABLE、REQUEST_TIMEOUT。
exists() 是只读探测,mode: 'read' 与 mode: 'readwrite' 均可调用;它不要求可信用户手势,
不会创建目录、枚举子项、读取文件内容、延长外部授权寿命或占用新的 direct-handle 配额。sandbox
lazy ref 会在每次调用时按当前 Mini-program identity 解析;picker 返回的外部目录授权只在当前
Runtime session 有效。
每次调用都会发送新的 directory.exists 请求并重新查询 Host,不读取或更新 SDK 本地缓存。
返回值只描述该次查询完成时的状态:目录可能在 Promise resolve 后立即被其他代码创建、删除或
替换,因此先 exists() 再 create() / list() 存在 TOCTOU 竞态。必须继续处理后续操作自身的
DIRECTORY_NOT_FOUND、FILE_TYPE_MISMATCH、授权和 I/O 错误;需要确保目录存在时,直接调用
create() 的幂等默认模式通常更合适。
Runtime 内部通过 Host directory stat 判断 kind,但公开 DirectoryHandle 没有 stat() 方法,
exists() 也不会暴露 size、时间戳或其他目录元数据。FileHandle.stat()
只适用于文件;不要把它当作目录元数据入口。需要直接子项时调用
list(),它会重新访问 Host,不复用本次存在性结果。
新 PC Host 支持该操作;Android / iOS 1.3.396+ 仅在 system.describe 宣告 files.stat 时启用,
OHOS 同样以 Host 实际协商结果为准。Web、Browser Dev Host、旧 Host 或缺少该 operation 的环境
fail closed,返回 METHOD_FORBIDDEN / METHOD_NOT_FOUND,不会用浏览器 File / Blob 或内存目录
伪造 false。该操作只读取元数据,不受移动端 8 MiB 完整文件内容读写上限影响。
import hbSDK, { HbMiniProgramSDKError } from '@heybox/hb-sdk'
const cache = hbSDK.files.sandbox.directory('cache/images')
try {
if (!(await cache.exists())) {
// 默认 create 是幂等的;recursive 同时确保父目录存在。
await cache.create({ recursive: true })
}
// exists() 与 list() 不是原子操作,list() 的错误仍需处理。
const entries = await cache.list({ limit: 100 })
console.log(entries.map(entry => entry.name))
} catch (error) {
if (error instanceof HbMiniProgramSDKError && error.code === 'DIRECTORY_NOT_FOUND') {
console.warn('目录在检查后被删除,请刷新状态后重试')
} else {
throw error
}
}
按规范相对路径派生文件代理。
相对于当前逻辑根、使用 / 分隔的规范路径。必须是非空字符串,不能以
/ 开头或结尾,不能包含空 segment、反斜杠、NUL 或其他控制字符;任一 segment 恰为 . 或
.. 都会拒绝,包括整个参数 '.'。.env、report..json 等不等于点段的普通名称可以使用。
当前 SDK session 内延迟访问目标文件的冻结
FileHandle。其 kind 固定为 'file',name 是
relativePath 的末段 basename,mode 继承当前逻辑根;因此 files.sandbox.file() 返回
readwrite,从用户选择目录继续派生时则继承所选目录的 read 或 readwrite,不能通过子路径
提升权限。
HbMiniProgramSDKError
relativePath 不是字符串、为空、以 / 开头或结尾,包含连续 /、任一 . / .. 点段、
反斜杠或控制字符时,同步抛出 INVALID_PARAMS。
该方法同步校验路径并创建 lazy proxy,不检查文件是否存在或创建文件,不读取内容或元数据,不发送
bridge 请求,也不会打开系统选择器。调用本身因此不需要用户手势,不会触发 Host operation,
不会占用 pickFiles() / saveFile() 的 direct handle 配额,也不会暴露宿主真实路径。
后续 I/O 才要求在 package.json#heybox.permissions 中声明并启用 filesystem,并由 Host 开放
对应 operation:FileHandle 的 create()、remove()、
exists()、readText()、readBytes()、writeText()、writeBytes()、stat() 分别使用
file.create、file.remove、file.exists、file.readText、file.readBytes、file.writeText、
file.writeBytes、file.stat。当前运行快照缺少或未启用所需权限时分别返回 PERMISSION_NOT_IN_SNAPSHOT 或
PERMISSION_DENIED,Host 未开放具体 operation 时返回 METHOD_FORBIDDEN;这些错误在调用异步
方法时发生,不由本方法抛出。
代理只表达目标位置。exists() 可区分文件缺失或目标实际为目录;create() 可显式确保文件存在,
writeText() / writeBytes() 也可隐式创建目标文件,但不会自动创建缺失的父目录。只读父目录派生
的文件可以读取与查询,调用 create()、写入或删除会返回 FILE_ACCESS_DENIED;外部目录派生的
文件即使是 readwrite 也不能删除。
若目标是目录或需要先创建父目录,使用 files.sandbox.directory()。若要让用户选择现有的精确外部 文件,使用 files.pickFiles();若要让用户指定新的精确可写目标, 使用 files.saveFile()。
import hbSDK from '@heybox/hb-sdk'
// 构造代理时没有 I/O,且不会隐式创建 reports 目录。
const report = hbSDK.files.sandbox.file('reports/latest.json')
console.log(report.kind, report.name, report.mode)
// file, latest.json, readwrite
await hbSDK.files.sandbox.directory('reports').create({ recursive: true })
await report.writeText(JSON.stringify({ generatedAt: Date.now() }))
if (await report.exists()) {
console.log(await report.readText())
console.log((await report.stat()).size)
}
枚举当前目录的直接子项。
可选options: ListOptions可选的单次结果数量上限。省略 options、传 {} 或省略 limit 时使用
1000;完整范围见 ListOptions。
当前目录直接子项的冻结 FileHandle / DirectoryHandle 代理数组;空目录
返回 []。数组与每个代理都是本次调用的新结果,条目 mode 与当前目录严格一致,name 只含
basename,不包含父路径或 Host 真实路径。不会递归返回后代。
HbMiniProgramSDKError options 不是对象,或 limit 不是正的 safe integer 时返回
INVALID_PARAMS;limit > 1000,或 Host 返回项目数超过有效 limit 时返回
DIRECTORY_LIST_LIMIT_EXCEEDED。
HbMiniProgramSDKError 当前目录或任一祖先不存在时返回 DIRECTORY_NOT_FOUND,目标
实际是文件时返回 FILE_TYPE_MISMATCH;外部 direct Directory 授权失效、来自其他或已结束的
Runtime session 时返回 FILE_ACCESS_REVOKED。
HbMiniProgramSDKError 当前运行快照缺少或未启用 filesystem 时返回
PERMISSION_NOT_IN_SNAPSHOT / PERMISSION_DENIED;Host 未开放或未协商到 directory.list 时返回
METHOD_FORBIDDEN,旧 Runtime 可返回 METHOD_NOT_FOUND。
HbMiniProgramSDKError Host 返回非数组、稀疏数组、非法 kind/name/mode/handle,或
子项不能安全派生为当前目录的直接后代时返回 FILE_IO_FAILED;其他 Host 枚举或底层 I/O 失败
返回对应稳定文件错误码,无法识别的 Host 错误统一为 FILE_IO_FAILED。
list() 只枚举一层,不排序、不去重,也不补齐分页。结果顺序以及达到 limit 时选择哪些条目
由 Host 文件系统决定;调用方不能依赖字母序、创建时间序或跨调用稳定顺序。需要稳定展示时应按
name 等业务规则自行排序。公开结果没有 total、hasMore 或 continuation cursor,因此
limit 不应被当作可完整遍历超大目录的分页协议。
Runtime 逐槽读取 Host 数组,拒绝稀疏或越界结果,并把每个 Host 文件/目录转换成当前目录的直接
子逻辑引用;SDK 再验证所有 descriptor 都继承父目录 mode。从 read 目录列出的代理仍只读,
从 readwrite 目录列出的代理可在原授权范围内写入,但枚举不会提升权限或扩大到父目录之外。
返回项不会作为新的 external direct handles 注册,因此不消耗 picker / saveFile() 共享的 1024
direct-handle 配额。它们仍依赖原目录的来源和生命周期:sandbox 子项按当前 Mini-program identity
解析;外部目录的子项只在原 direct Directory 所属的当前 Runtime session 内有效,session 结束或
授权撤销后后续操作会失败。列表只是本次枚举快照,返回后文件系统可以继续变化。
mode: 'read' 与 mode: 'readwrite' 目录都能调用。该方法不要求可信用户手势,不创建、读取或
修改文件内容;外部目录只有最初调用 pickDirectory() 时需要手势。新 PC Host 支持该操作;
Android / iOS 1.3.396+ 仅在 system.describe 宣告 files.list 时逐项启用,OHOS 同样以 Host
实际协商结果为准。Web、Browser Dev Host、旧 Host 或 operation 缺失时 fail closed,不提供
浏览器文件系统、File / Blob 或内存 fallback。
若只需判断目录本身是否存在,使用 exists()。已知子项名称时, 可直接通过当前目录的 file() 或 directory() 构造 lazy proxy,无需先枚举;这两个方法同样不会执行 I/O 或占用 direct-handle 配额。
import hbSDK from '@heybox/hb-sdk'
const reports = hbSDK.files.sandbox.directory('reports')
await reports.create({ recursive: true })
await reports.file('summary.json').writeText('{}')
await reports.directory('archive').create()
const entries = await reports.list({ limit: 100 })
const sorted = [...entries].sort((left, right) => left.name.localeCompare(right.name))
for (const entry of sorted) {
if (entry.kind === 'file') console.log('file', entry.name, await entry.stat())
else console.log('directory', entry.name, await entry.exists())
}
删除当前代理指向的 sandbox 目录。
可选options: RemoveOptions可选删除配置。省略 options、传 {} 或省略 recursive 都等同于
{ recursive: false };此时只允许删除空目录。recursive 必须是 boolean,非对象 options、
数组或其他类型会以 INVALID_PARAMS 拒绝。
Host 报告目标目录删除完成后以 undefined resolve。不返回删除的子项数量、原目录
内容或新的 handle;当前 DirectoryHandle 仍是同一逻辑位置的代理,可继续调用
exists() 或 create()。
HbMiniProgramSDKError 当前代理不是 readwrite,来源是 pickDirectory() 返回的
外部目录,或从外部目录派生/枚举得到时,在发送 bridge 请求前以 FILE_ACCESS_DENIED 拒绝。
外部目录授权即使为 readwrite 也不能删除其自身或任何后代。
HbMiniProgramSDKError 删除 files.sandbox.directory('.') 表示的 sandbox 根目录时
以 FILE_ACCESS_DENIED 拒绝;recursive: true 也不能绕过该边界。目标目录非空且
recursive 为默认的 false 时返回 DIRECTORY_NOT_EMPTY。
HbMiniProgramSDKError 目标或任一祖先不存在时返回 DIRECTORY_NOT_FOUND,目标
实际是文件或路径中的祖先类型不匹配时返回 FILE_TYPE_MISMATCH。删除已经不存在的目录不会
当作幂等成功;需要“确保不存在”语义时应先接受缺失错误或在操作后调用 exists() 对账。
HbMiniProgramSDKError 当前运行快照缺少或未启用 filesystem 权限时分别以
PERMISSION_NOT_IN_SNAPSHOT、PERMISSION_DENIED 拒绝;Host 未开放 directory.remove 时以
METHOD_FORBIDDEN 拒绝,旧 Runtime 也可能返回 METHOD_NOT_FOUND。
HbMiniProgramSDKError SDK 已销毁、Runtime 已卸载、请求超时、Host 拒绝删除或
发生底层 I/O 失败时,以 SDK_DESTROYED、RUNTIME_UNAVAILABLE、REQUEST_TIMEOUT、
FILE_ACCESS_DENIED、FILE_IO_FAILED 或 Host 保留的对应稳定文件错误码拒绝。
该方法只对当前 Mini-program identity 的 sandbox 子目录开放,并要求代理的
mode === 'readwrite'。它不需要可信用户手势、不打开系统选择器、不暴露真实路径,也不会因为
传入 recursive: true 而跨出当前逻辑目录。picker 只负责授予外部访问,不能授予删除外部目录
树的能力;这一来源限制独立于 mode 和 Host 原生权限。
recursive: false 是保护性默认值:空目录会删除,存在任意直接或间接子项时应返回
DIRECTORY_NOT_EMPTY,且不应由 Runtime 自动重试为递归删除。recursive: true 明确授权 Host
删除该目录及其整个后代,包括文件、空目录和非空目录。Promise 只反映 Host 对本次请求的最终
结果;公开合同不承诺多对象删除具备事务原子性或失败后自动恢复已删除子项。
删除成功后,当前代理对象不会失效或自动改变 name / mode。随后
exists() 应在目标仍不存在时返回 false,也可以调用
create() 在同一 sandbox 位置重新创建。两次调用之间仍存在
并发变化窗口,因此删除前的 exists() 或 list() 不能保证后续删除成功。
若只需删除单个 sandbox 文件,使用 FileHandle.remove();它没有
recursive 选项。若希望保留目录并清理部分内容,应先通过 list() 取得直接子项,再按业务规则
删除 sandbox 项;不要对外部授权项调用 remove。
新 PC Host 支持该操作;Android / iOS 1.3.396+ 仅在 system.describe 宣告
files.remove 时逐项启用,OHOS 同样以 Host 实际协商结果为准。Web、Browser Dev Host、旧 Host
或缺少该 operation 的环境会 fail closed,不提供浏览器文件系统或内存 fallback;页面应处理
METHOD_FORBIDDEN,不要仅按操作系统推断可用性。
import hbSDK, { HbMiniProgramSDKError } from '@heybox/hb-sdk'
const cache = hbSDK.files.sandbox.directory('cache')
await cache.create({ recursive: true })
await cache.file('index.json').writeText('{}')
try {
await cache.remove() // 默认 recursive: false,非空目录会拒绝。
} catch (error) {
if (!(error instanceof HbMiniProgramSDKError) || error.code !== 'DIRECTORY_NOT_EMPTY') {
throw error
}
}
await cache.remove({ recursive: true })
console.log(await cache.exists()) // false
// 代理仍表示同一个 sandbox 位置。
await cache.create()
当前 SDK session 中的目录代理。
备注
目录既能执行目录操作,也是派生子 File/Directory 逻辑代理的根。派生代理继承目录的
mode, 不能通过子路径提升授权范围。