跳到内容
Tauri

嵌入附加文件

你可能需要在应用程序包中包含一些不直接属于你的前端(即 frontendDist)或者太大而无法直接嵌入到二进制文件中的额外文件。我们将这些文件称为 resources(资源)。

要打包你选择的文件,请在 tauri.conf.json 文件中将 resources 属性添加到 bundle 对象中。

包含文件列表

tauri.conf.json
{
"bundle": {
"resources": [
"./path/to/some-file.txt",
"/absolute/path/to/textfile.txt",
"../relative/path/to/jsonfile.json",
"some-folder/",
"resources/**/*.md"
]
}
}

打包后的文件将位于 $RESOURCES/ 目录下,并保留原始的目录结构,例如:./path/to/some-file.txt -> $RESOURCE/path/to/some-file.txt

若要精细控制文件的复制目标位置,请改用映射(map)方式

tauri.conf.json
{
"bundle": {
"resources": {
"/absolute/path/to/textfile.txt": "resources/textfile.txt",
"relative/path/to/jsonfile.json": "resources/jsonfile.json",
"resources/": "",
"docs/**/*md": "website-docs/"
}
}
}

要了解 $RESOURCE 在各平台上的解析位置,请参阅 resource_dir 的文档。

源路径语法

在以下说明中,“目标资源目录”指的是对象表示法中冒号后的值,或者数组表示法中原始文件路径的重构路径。

  • "dir/file.txt":将 file.txt 文件复制到目标资源目录中。
  • "dir/":将所有文件和目录递归复制到目标资源目录中。如果你想保留文件和目录的文件系统结构,请使用此项。
  • "dir/*":将 dir 目录下的所有文件非递归地(子目录将被忽略)复制到目标资源目录中。
  • "dir/**":会抛出错误,因为 ** 仅匹配目录,因此找不到任何文件。
  • "dir/**/*":将 dir 目录下的所有文件递归地(包括 dir/ 下的所有文件以及所有子目录中的所有文件)复制到目标资源目录中。
  • "dir/**/**":会抛出错误,因为 ** 仅匹配目录,因此找不到任何文件。

要解析资源文件的路径,请使用以下 API,而不是手动计算路径:

在 Rust 端,你需要一个 PathResolver 实例,你可以从 AppAppHandle 获取它,然后调用 PathResolver::resolve

tauri::Builder::default()
.setup(|app| {
let resource_path = app.path().resolve("lang/de.json", BaseDirectory::Resource)?;
Ok(())
})

在命令(Command)中使用:

#[tauri::command]
fn hello(handle: tauri::AppHandle) {
let resource_path = handle.path().resolve("lang/de.json", BaseDirectory::Resource)?;
}

API 调用中的路径可以是普通的相对路径(如 folder/json_file.json,解析为 $RESOURCE/folder/json_file.json),也可以是类似 ../relative/folder/toml_file.toml 的路径(解析为 $RESOURCE/_up_/relative/folder/toml_file.toml)。这些 API 使用与在 tauri.conf.json > bundle > resources 中编写时相同的规则,例如:

tauri.conf.json
{
"bundle": {
"resources": ["folder/json_file.json", "../relative/folder/toml_file.toml"]
}
}
let json_path = app.path().resolve("folder/json_file.json", BaseDirectory::Resource)?;
let toml_path = app.path().resolve("../relative/folder/toml_file.toml", BaseDirectory::Resource)?;

目前,资源在 APK 中作为资产(assets)存储,因此这些 API 的返回值并不是普通的文件系统路径。我们在此处使用了一个特殊的 URI 前缀 asset:///,它可以配合 fs 插件使用。通过该插件,你可以使用 FsExt::fs 读取文件,如下所示:

let resource_path = app.path().resolve("lang/de.json", BaseDirectory::Resource).unwrap();
let json = app.fs().read_to_string(&resource_path);

如果你希望或必须将资源文件放在实际的文件系统中,请通过 fs 插件手动复制内容。

在此示例中,我们想要捆绑额外的 i18n JSON 文件,如下所示:

.
├── src-tauri/
│ ├── tauri.conf.json
│ ├── lang/
│ │ ├── de.json
│ │ └── en.json
│ └── ...
└── ...
tauri.conf.json
{
"bundle": {
"resources": ["lang/*"]
}
}
lang/de.json
{
"hello": "Guten Tag!",
"bye": "Auf Wiedersehen!"
}

在 Rust 端,你需要一个 PathResolver 实例,你可以从 AppAppHandle 获取它。

tauri::Builder::default()
.setup(|app| {
// The path specified must follow the same syntax as defined in
// `tauri.conf.json > bundle > resources`
let resource_path = app.path().resolve("lang/de.json", BaseDirectory::Resource)?;
let json = std::fs::read_to_string(&resource_path).unwrap();
// Or when dealing with Android, use the file system plugin instead
// let json = app.fs().read_to_string(&resource_path);
let lang_de: serde_json::Value = serde_json::from_str(json).unwrap();
// This will print 'Guten Tag!' to the terminal
println!("{}", lang_de.get("hello").unwrap());
Ok(())
})
#[tauri::command]
fn hello(handle: tauri::AppHandle) -> String {
let resource_path = handle.path().resolve("lang/de.json", BaseDirectory::Resource)?;
let json = std::fs::read_to_string(&resource_path).unwrap();
// Or when dealing with Android, use the file system plugin instead
// let json = handle.fs().read_to_string(&resource_path);
let lang_de: serde_json::Value = serde_json::from_str(json).unwrap();
lang_de.get("hello").unwrap()
}

对于 JavaScript 端,你可以使用类似上述的命令并通过 await invoke('hello') 调用,或者使用 fs 插件访问这些文件。

使用 fs 插件时,除了基本设置外,你还需要配置访问控制列表(ACL)以启用所需的插件 API,以及授予访问 $RESOURCE 文件夹的权限。

src-tauri/capabilities/default.json
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "main-capability",
"description": "Capability for the main window",
"windows": ["main"],
"permissions": [
"core:default",
"fs:allow-read-text-file",
"fs:allow-resource-read-recursive"
]
}
import { resolveResource } from '@tauri-apps/api/path';
import { readTextFile } from '@tauri-apps/plugin-fs';
const resourcePath = await resolveResource('lang/de.json');
const langDe = JSON.parse(await readTextFile(resourcePath));
console.log(langDe.hello); // This will print 'Guten Tag!' to the devtools console

由于我们在使用列表时将相对路径中的 ../ 替换为 _up_,将绝对路径中的根目录替换为 _root_,这些文件将位于资源目录内的子文件夹中。为了在 Tauri 的 权限系统中允许这些路径,请使用 $RESOURCE/**/* 来允许对这些文件的递归访问。

对于这样打包的文件:

tauri.conf.json
{
"bundle": {
"resources": ["../relative/path/to/jsonfile.json"]
}
}

配合 fs 插件使用:

src-tauri/capabilities/default.json
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "main-capability",
"description": "Capability for the main window",
"windows": ["main"],
"permissions": [
"core:default",
"fs:allow-stat",
"fs:allow-read-text-file",
"fs:allow-resource-read-recursive",
{
"identifier": "fs:scope",
"allow": ["$RESOURCE/**/*"],
"deny": ["$RESOURCE/secret.txt"]
}
]
}

配合 opener 插件使用:

src-tauri/capabilities/default.json
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "main-capability",
"description": "Capability for the main window",
"windows": ["main"],
"permissions": [
"core:default",
{
"identifier": "opener:allow-open-path",
"allow": [
{
"path": "$RESOURCE/**/*"
}
]
}
]
}

© 2026 Tauri 贡献者。CC-BY / MIT