Saltar al contenido

Incrustar archivos adicionales

Es posible que necesitas incluir archivos adicionales en el paquete de tu aplicación que no formen parte directamente de tu frontend (tu frontendDist) o que sean demasiado grandes para insertarse directamente en el binario. A estos archivos los llamamos recursos.

Para empaquetar los archivos que elijas, añade la propiedad resources al objeto bundle en tu archivo tauri.conf.json.

Para incluir una lista de archivos:

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

Los archivos empaquetados estarán en $RESOURCES/ conservando la estructura de directorios original, por ejemplo: ./path/to/some-file.txt -> $RESOURCE/path/to/some-file.txt

Para tener un control preciso sobre dónde se copiarán los archivos, usa un mapa en su lugar:

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/"
}
}
}

Para obtener más información sobre a dónde se resuelve $RESOURCE en cada plataforma, consulta la documentación de resource_dir

Sintaxis de la ruta de origen

En las siguientes explicaciones, "directorio de recursos de destino" es el valor después de los dos puntos en la notación de objeto, o una reconstrucción de las rutas de archivo originales en la notación de arreglo.

  • "dir/file.txt": copia el archivo file.txt en el directorio de recursos de destino.
  • "dir/": copia todos los archivos y directorios de forma recursiva en el directorio de recursos de destino. Usa esto si también quieres conservar la estructura del sistema de archivos de tus archivos y directorios.
  • "dir/*": copia todos los archivos del directorio dir de forma no recursiva (se ignorarán los subdirectorios) en el directorio de recursos de destino.
  • "dir/**: lanza un error porque ** solo coincide con directorios y por lo tanto no se pueden encontrar archivos.
  • "dir/**/*": copia todos los archivos del directorio dir de forma recursiva (todos los archivos en dir/ y todos los archivos en todos los subdirectorios) en el directorio de recursos de destino.
  • "dir/**/**: lanza un error porque ** solo coincide con directorios y por lo tanto no se pueden encontrar archivos.

Para resolver la ruta de un archivo de recursos, en lugar de calcular manualmente la ruta, usa las siguientes API

En el lado de Rust, necesitas una instancia de PathResolver que puedes obtener de App y AppHandle, y luego llamar a PathResolver::resolve:

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

Para usarlo en un comando:

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

La ruta en las llamadas a la API puede ser una ruta relativa normal como folder/json_file.json que se resuelve a $RESOURCE/folder/json_file.json, o rutas como ../relative/folder/toml_file.toml que se resuelven a $RESOURCE/_up_/relative/folder/toml_file.toml, estas API usan las mismas reglas que cuando escribes en tauri.conf.json > bundle > resources, por ejemplo:

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)?;

Actualmente los recursos se almacenan en el APK como assets, por lo que el valor devuelto por esas API no son rutas normales del sistema de archivos, aquí usamos un prefijo URI especial asset://localhost/ que se puede usar con el plugin fs, con eso, puedes leer los archivos a través de FsExt::fs de esta manera:

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

Si quieres o necesitas que los archivos de recursos estén en un sistema de archivos real, copia los contenidos manualmente a través del plugin fs

En este ejemplo queremos empaquetar archivos json de i18n adicionales como este:

.
├── 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!"
}

En el lado de Rust, necesitas una instancia de PathResolver que puedes obtener de App y AppHandle:

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()
}

En el lado de JavaScript, puedes usar un comando como el anterior y llamarlo a través de await invoke('hello') o acceder a los archivos usando el plugin fs.

Al usar el plugin fs, además de la configuración básica, también tendrás que configurar la lista de control de acceso para habilitar cualquier API de plugin que necesites, así como los permisos para acceder a la carpeta $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

Dado que reemplazamos ../ por _up_ en rutas relativas y la raíz por _root_ en rutas absolutas cuando se usa una lista, esos archivos estarán en subcarpetas dentro del directorio de recursos. Para permitir esas rutas en el sistema de permisos de Tauri, usa $RESOURCE/**/* para permitir el acceso recursivo a esos archivos

Con un archivo empaquetado así:

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

Para usarlo con el plugin 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"]
}
]
}

Para usarlo con el plugin 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 Colaboradores de Tauri. CC-BY / MIT