Skip to content

Commit 70b74d0

Browse files
committed
feat(path): add convert_file_src to PathResolver
Adds a Rust equivalent of the JavaScript `convertFileSrc` function to the PathResolver API, enabling file-to-URL conversion from Rust code. This is useful when processing file paths in Rust (e.g., parsing markdown with image references) and needing to convert them to URLs that the webview can load. The implementation: - Uses percent-encoding for URL-safe path encoding - Uses dunce::simplified to normalize Windows paths - Returns HTTP URLs on Windows/Android and custom protocol URLs elsewhere Closes #12022
1 parent 123d63a commit 70b74d0

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

crates/tauri/src/path/android.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use super::Result;
66
use crate::{plugin::PluginHandle, Runtime};
7+
use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
78
use std::path::{Path, PathBuf};
89

910
/// A helper class to access the mobile path APIs.
@@ -175,4 +176,36 @@ impl<R: Runtime> PathResolver<R> {
175176
pub fn home_dir(&self) -> Result<PathBuf> {
176177
self.call_resolve("getHomeDir")
177178
}
179+
180+
/// Converts a file path to a URL that can be loaded by the webview.
181+
///
182+
/// This is the Rust equivalent of the JavaScript `convertFileSrc` function.
183+
/// Note: The file must be allowed by the app's asset scope for the webview to load it.
184+
///
185+
/// # Arguments
186+
///
187+
/// * `path` - The file path to convert
188+
/// * `protocol` - The protocol to use, defaults to `"asset"` if `None`
189+
///
190+
/// # Examples
191+
///
192+
/// ```rust,no_run
193+
/// use tauri::Manager;
194+
/// tauri::Builder::default()
195+
/// .setup(|app| {
196+
/// let video_path = app.path().app_data_dir()?.join("video.mp4");
197+
/// let url = app.path().convert_file_src(&video_path, None);
198+
/// // On Android: http://asset.localhost/...
199+
/// println!("URL: {}", url);
200+
/// Ok(())
201+
/// });
202+
/// ```
203+
pub fn convert_file_src<P: AsRef<Path>>(&self, path: P, protocol: Option<&str>) -> String {
204+
let protocol = protocol.unwrap_or("asset");
205+
let path = path.as_ref();
206+
let encoded = utf8_percent_encode(&path.to_string_lossy(), NON_ALPHANUMERIC).to_string();
207+
208+
// Android uses HTTP protocol like Windows
209+
format!("http://{protocol}.localhost/{encoded}")
210+
}
178211
}

crates/tauri/src/path/desktop.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use super::{Error, Result};
66
use crate::{AppHandle, Manager, Runtime};
7+
use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
78
use std::path::{Path, PathBuf};
89

910
/// The path resolver is a helper class for general and application-specific path APIs.
@@ -293,4 +294,43 @@ impl<R: Runtime> PathResolver<R> {
293294
pub fn temp_dir(&self) -> Result<PathBuf> {
294295
Ok(std::env::temp_dir())
295296
}
297+
298+
/// Converts a file path to a URL that can be loaded by the webview.
299+
///
300+
/// This is the Rust equivalent of the JavaScript `convertFileSrc` function.
301+
/// Note: The file must be allowed by the app's asset scope for the webview to load it.
302+
///
303+
/// # Arguments
304+
///
305+
/// * `path` - The file path to convert
306+
/// * `protocol` - The protocol to use, defaults to `"asset"` if `None`
307+
///
308+
/// # Examples
309+
///
310+
/// ```rust,no_run
311+
/// use tauri::Manager;
312+
/// tauri::Builder::default()
313+
/// .setup(|app| {
314+
/// let video_path = app.path().app_data_dir()?.join("video.mp4");
315+
/// let url = app.path().convert_file_src(&video_path, None);
316+
/// // On Windows: http://asset.localhost/C%3A%5CUsers%5C...
317+
/// // On macOS/Linux: asset://localhost/%2FUsers%2F...
318+
/// println!("URL: {}", url);
319+
/// Ok(())
320+
/// });
321+
/// ```
322+
pub fn convert_file_src<P: AsRef<Path>>(&self, path: P, protocol: Option<&str>) -> String {
323+
let protocol = protocol.unwrap_or("asset");
324+
let path = dunce::simplified(path.as_ref());
325+
let encoded = utf8_percent_encode(&path.to_string_lossy(), NON_ALPHANUMERIC).to_string();
326+
327+
#[cfg(windows)]
328+
{
329+
format!("http://{protocol}.localhost/{encoded}")
330+
}
331+
#[cfg(not(windows))]
332+
{
333+
format!("{protocol}://localhost/{encoded}")
334+
}
335+
}
296336
}

0 commit comments

Comments
 (0)