@mptool/file
File API
Tips
The framework automatically prepends USER_DATA_PATH, so you do not need to handle it yourself.
All path arguments are normalized first (leading / removed, repeated / collapsed, . and .. resolved). If a path escapes the user directory through .. (for example ../secret or a/../../b), an MpError is thrown directly instead of treating the path as "file not found".
Utilities
dirname(path: string): stringReturns the directory part of a path
exists(path: string): booleanReturns whether a file or directory exists. Returns
falseonly when the file genuinely does not exist; other errors such as permission or I/O errors throw anMpErrorinstead of being disguised as "not found".Tips
Read APIs (
exists/ls/readFile/readJSON) return the default value only when "the target does not exist"; all other errors throw anMpError.isDir(path: string): booleanReturns whether the path is a directory
isFile(path: string): booleanReturns whether the path is a file
Reading
ls(path: string): string[]Lists all contents of a directory as an array
readFile(path: string, encoding?: string): string | ArrayBuffer | undefinedReads and returns the contents of the file at the specified path. Returns
undefinedwhen the file does not exist.encodingis the file encoding; optional, defaults to"utf-8"readJSON(path: string, encoding = 'utf-8'): any | undefinedReads serializable file data and returns the parsed result.
Returns
undefinedwhen the JSON file does not exist or parsing failspath: the file path to read; it should not include the.jsonsuffixencoding: the file encoding; optional, defaults toutf-8
Operations
mkdir(path: string, recursive = true): voidCreates a directory. The optional second argument,
recursive, controls whether parent directories are created recursively; by default they are.rm(path: string, type?: "dir" | "file"): voidDeletes the specified path.
The optional second argument,
type, can be"dir"or"file"; providing it improves deletion performancewriteFile(path: string, data: any, encoding?: string): voidWrites a file
path: the file path to write; the file or its parent directory is created automatically if missingdata: the data to write. Strings are written as-is (not JSON-serialized),ArrayBuffer/TypedArray/DataVieware written as raw binary, and other data is JSON-serializedencoding: file encoding option; optional, defaults tobinaryfor binary data andutf-8otherwise
writeJSON(path: string, data: any, encoding = 'utf-8'): voidWrites serializable data as JSON
path: the file path to write; the parent directory is created automatically if missingdata: the data to write; it must be JSON-serializableencoding: file encoding option; defaults toutf-8
Warning
undefined, functions, Symbols and circular references cannot be represented correctly byJSON.stringify;writeJSONthrows anMpErrorinstead of silently writingundefined/null.saveFile(tempFilePath: string, path: string): stringSaves a temporary file to local file storage and returns the saved path provided by
wx.saveFileSync; throws anMpErrorwhen saving fails.tempFilePath: the temporary file pathpath: the saved file path
saveOnlineFile(onlinePath: string, localPath: string): Promise<string> & { task: DownloadTask }Saves an online file to the specified local location and returns the saved local file path;
taskon the return value is the underlyingDownloadTask, so for large downloads you can calltask.abort()to cancel ortask.onProgressUpdate()to monitor progress.onlinePath: the online file pathlocalPath: the local file path
Tips
The destination directory is created automatically.
unzip(zipFilePath: string, targetPath: string): Promise<void>Extracts an archive
zipFilePath: the archive path to extracttargetPath: the destination directory
Tips
The destination directory is created automatically.
Storage API
Put and take
put and take can store any data, but stored data can be taken only once and is valid only during the current mini-program launch.
They use separate in-memory storage (the exported storage Map) that is not connected to the persistent storage of set / get below. To ensure there are no leftovers where a value has been removed but can still be taken, remove / removeAsync / check / checkAsync also clear the in-memory value with the same name.
Tips
For performance, and because mini-programs handle Function specially, stored data is not deep-copied.
put<T = unknown>(key: string, data: T): void: stores data.take<T = unknown>(key: string): T | undefined: takes dataTips
Once data has been taken, subsequent calls return
undefined.
Persistent data
Data set with get and set is persistent and can have an expiration time.
Warning
Due to an issue in the underlying WeChat mini-program implementation, automatic cleanup happens only on the next read that discovers the data has expired. If there is no subsequent read of the corresponding storage, the data stays there forever (even after it expires).
Therefore, if you use a large number of temporary keys, you may need to manually check and clear expired data periodically with check.
set(key: string, value: any, expire?: number | 'once' | 'keep' = 0): voidSets data synchronously.
key: the key name to setvalue: the value to storeexpire: expiration time; optional, defaults to00: default, valid forever'once': valid only for the current launch'keep': keeps the previous expiration time- number: validity period in milliseconds
Tips
Note that when
'keep'is passed and no key with the same name exists in storage, the value is not written either.Warning
'keep'is implemented as "read the old expiration time, then write the new value" and is not atomic. If other writes to the same key happen concurrently (especiallysetAsyncwrites that have not completed), the retained expiration time may not be the one from the latest write. Do not rely on the expiration time of'keep'in concurrent scenarios.Warning
If the write fails (for example because the storage quota is full),
setthrows anMpErrorwhosemessagecontains theerrMsgreturned by WeChat. Callers should usetry/catch.setAsync(key: string, value: any, expire?: number | 'once' | 'keep' = 0): Promise<WechatMiniprogram.GeneralCallbackResult | void>The asynchronous version of
set; consider using it when setting large amounts of data. Returns a Promise.expireaccepts the same values assetand defaults to0(valid forever).When the write fails, the returned Promise rejects with an
MpError(consistent withsetthrowing); callers should usetry/catchor.catch().get<T = unknown>(key: string): T | undefinedReads and returns data synchronously.
Returns
undefinedwhen the data has expired.'once'data is valid only for the current launch; a numeric expiration time is calculated from the write time.key: the key name to read
getAsync<T = unknown>(key: string): Promise<T | undefined>The asynchronous version of
get; consider using it when reading large amounts of data to avoid blocking the thread. Returns a Promise.key: the key name to read
It resolves to
undefinedonly when the key does not exist (getStorage:fail data not foundfrom WeChat); other read errors (permission, corrupted storage, etc.) reject with anMpErrorand are not treated as "no cache".remove(key: string): voidDeletes data synchronously.
key: the key name to delete
removeAsync(key: string): Promise<void>Deletes data asynchronously. Returns a Promise.
key: the key name to delete
check(): voidChecks and clears expired data synchronously.
checkAsync(): Promise<void>Checks and clears expired data asynchronously. Returns a Promise.