人人都会AI编程

文件读写、目录操作、权限控制

更新时间:2026-07-11

在 Tauri 中,文件系统操作并非像传统 Node.js 那样可以任意调用,而是严格遵循“默认拒绝、按需授权”的安全策略。所有文件读写和目录操作都必须通过 Rust 后端执行,前端通过 IPC 命令触发,并在配置中显式声明允许访问的路径或范围。这种设计既保证了功能的可用性,又避免了恶意网页利用漏洞访问用户敏感文件。


权限控制:安全的第一道关卡

tauri.conf.json 中,你需要定义一个或多个权限(permission),并将其分配给相应的命令或前端窗口。通常使用 Tauri 内置的文件系统插件(@tauri-apps/plugin-fs)来实现读写操作,该插件已经封装了大部分安全检查和跨平台兼容性。

一个典型的权限配置如下(tauri.conf.json 中的 plugins.fs 部分):

{
  "plugins": {
    "fs": {
      "scope": {
        "allow": [
          {
            "path": "$APPDATA/my-app/**",
            "read": true,
            "write": true
          },
          {
            "path": "$HOME/Documents/**",
            "read": true
          }
        ],
        "deny": [
          {
            "path": "$HOME/Documents/passwords.txt"
          }
        ]
      }
    }
  }
}

关键点

  • 路径前缀:使用如 $APPDATA$HOME$RESOURCE 等变量指定作用域,避免硬编码绝对路径,提高跨平台兼容性。
  • 读写分离:可以仅授予“只读”权限,而不能写入,满足最小权限原则。
  • 精细化与拒绝列表:允许某目录的同时,可以单独禁止特定文件或子目录。
  • 前端不可直接绕过:即使用户的前端代码被注入恶意脚本,攻击者也只能在你预先声明的范围内读写文件,无法访问任意位置。

文件读写:像操作普通 API 一样简单

在前端,安装插件后可以直接调用 @tauri-apps/plugin-fs 提供的函数。这些函数都是异步的,返回 Promise,不会阻塞 UI。

读取文本文件

import { readTextFile } from '@tauri-apps/plugin-fs';

const content = await readTextFile('settings.json'); // 路径相对于声明的 scope

如果文件不存在,会抛出异常,可以用 try/catch 处理。

写入字符串

import { writeTextFile } from '@tauri-apps/plugin-fs';

await writeTextFile('settings.json', JSON.stringify({ theme: 'dark' }));

二进制文件读写
使用 readFilewriteFile,返回和接收 Uint8Array,适合图像、PDF 等。


目录操作:创建、枚举、删除

同样需要提前声明路径权限。常用的目录操作包括:

创建目录

import { mkdir } from '@tauri-apps/plugin-fs';
await mkdir('screenshots', { recursive: true }); // 递归创建

列出目录内容

import { readDir } from '@tauri-apps/plugin-fs';

const entries = await readDir('screenshots');
for (const entry of entries) {
  console.log(entry.name, entry.isDirectory, entry.isFile);
}

删除文件或目录

import { remove, removeDir } from '@tauri-apps/plugin-fs';
await remove('temp.txt'); // 删除文件
await removeDir('backups', { recursive: true }); // 删除整个目录

检查路径存在性与元数据

import { exists, stat } from '@tauri-apps/plugin-fs';

if (await exists('config.json')) {
  const meta = await stat('config.json');
  console.log(meta.size, meta.mtime);
}

实际开发中的最佳实践

  • 尽量把数据写在应用专属目录:使用 $APPDATA/my-app 或 Tauri 提供的 appDataDir() API 获取路径,不要随意向 $HOME 根目录写入文件。
  • 将复杂逻辑放在 Rust 后端:如果需要加密解密、处理大文件流、数据备份等,建议用 Rust 命令实现,前端只负责发起触发。这样可以利用 Rust 的性能,并且减少前端代码对文件系统的直接依赖。
  • 测试权限边界:在开发阶段故意用前端调用未允许的路径,观察应用是否能正确返回权限拒绝错误(不应该崩溃),保证沙箱机制有效。
  • 跨平台路径处理:权限配置中的变量(如 $APPDATA)会在运行时自动映射到对应平台的路径(Windows 上是 C:\Users\<user>\AppData\Roaming,macOS 上是 ~/Library/Application Support),避免你自己做平台判断。

借助 Tauri 的文件系统插件,你可以用熟悉的 Promise 语法实现可靠的文件管理,而底层的权限模型和 Rust 的隔离执行则确保了用户数据的安全。这种“上层易用、底层牢固”的设计,正是 Tauri 在处理本地资源时的核心优势。