file_system.rs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. use crate::ApplicationDispatcherExt;
  2. use tauri_api::dir;
  3. use tauri_api::file;
  4. use tauri_api::path::resolve_path;
  5. use std::fs;
  6. use std::fs::File;
  7. use std::io::Write;
  8. use std::path::PathBuf;
  9. use super::cmd::{DirOperationOptions, FileOperationOptions};
  10. /// Reads a directory.
  11. #[cfg(read_dir)]
  12. pub async fn read_dir<D: ApplicationDispatcherExt>(
  13. dispatcher: &mut D,
  14. path: PathBuf,
  15. options: Option<DirOperationOptions>,
  16. callback: String,
  17. error: String,
  18. ) {
  19. crate::execute_promise(
  20. dispatcher,
  21. async move {
  22. let (recursive, dir) = if let Some(options_value) = options {
  23. (options_value.recursive, options_value.dir)
  24. } else {
  25. (false, None)
  26. };
  27. dir::read_dir(resolve_path(path, dir)?, recursive).map_err(crate::Error::FailedToExecuteApi)
  28. },
  29. callback,
  30. error,
  31. )
  32. .await;
  33. }
  34. /// Copies a file.
  35. #[cfg(copy_file)]
  36. pub async fn copy_file<D: ApplicationDispatcherExt>(
  37. dispatcher: &mut D,
  38. source: PathBuf,
  39. destination: PathBuf,
  40. options: Option<FileOperationOptions>,
  41. callback: String,
  42. error: String,
  43. ) {
  44. crate::execute_promise(
  45. dispatcher,
  46. async move {
  47. let (src, dest) = match options.and_then(|o| o.dir) {
  48. Some(dir) => (
  49. resolve_path(source, Some(dir.clone()))?,
  50. resolve_path(destination, Some(dir))?,
  51. ),
  52. None => (source, destination),
  53. };
  54. fs::copy(src, dest)?;
  55. crate::Result::Ok(())
  56. },
  57. callback,
  58. error,
  59. )
  60. .await;
  61. }
  62. /// Creates a directory.
  63. #[cfg(create_dir)]
  64. pub async fn create_dir<D: ApplicationDispatcherExt>(
  65. dispatcher: &mut D,
  66. path: PathBuf,
  67. options: Option<DirOperationOptions>,
  68. callback: String,
  69. error: String,
  70. ) {
  71. crate::execute_promise(
  72. dispatcher,
  73. async move {
  74. let (recursive, dir) = if let Some(options_value) = options {
  75. (options_value.recursive, options_value.dir)
  76. } else {
  77. (false, None)
  78. };
  79. let resolved_path = resolve_path(path, dir)?;
  80. if recursive {
  81. fs::create_dir_all(resolved_path)?;
  82. } else {
  83. fs::create_dir(resolved_path)?;
  84. }
  85. crate::Result::Ok(())
  86. },
  87. callback,
  88. error,
  89. )
  90. .await;
  91. }
  92. /// Removes a directory.
  93. #[cfg(remove_dir)]
  94. pub async fn remove_dir<D: ApplicationDispatcherExt>(
  95. dispatcher: &mut D,
  96. path: PathBuf,
  97. options: Option<DirOperationOptions>,
  98. callback: String,
  99. error: String,
  100. ) {
  101. crate::execute_promise(
  102. dispatcher,
  103. async move {
  104. let (recursive, dir) = if let Some(options_value) = options {
  105. (options_value.recursive, options_value.dir)
  106. } else {
  107. (false, None)
  108. };
  109. let resolved_path = resolve_path(path, dir)?;
  110. if recursive {
  111. fs::remove_dir_all(resolved_path)?;
  112. } else {
  113. fs::remove_dir(resolved_path)?;
  114. }
  115. crate::Result::Ok(())
  116. },
  117. callback,
  118. error,
  119. )
  120. .await;
  121. }
  122. /// Removes a file
  123. #[cfg(remove_file)]
  124. pub async fn remove_file<D: ApplicationDispatcherExt>(
  125. dispatcher: &mut D,
  126. path: PathBuf,
  127. options: Option<FileOperationOptions>,
  128. callback: String,
  129. error: String,
  130. ) {
  131. crate::execute_promise(
  132. dispatcher,
  133. async move {
  134. let resolved_path = resolve_path(path, options.and_then(|o| o.dir))?;
  135. fs::remove_file(resolved_path)?;
  136. crate::Result::Ok(())
  137. },
  138. callback,
  139. error,
  140. )
  141. .await;
  142. }
  143. /// Renames a file.
  144. #[cfg(rename_file)]
  145. pub async fn rename_file<D: ApplicationDispatcherExt>(
  146. dispatcher: &mut D,
  147. old_path: PathBuf,
  148. new_path: PathBuf,
  149. options: Option<FileOperationOptions>,
  150. callback: String,
  151. error: String,
  152. ) {
  153. crate::execute_promise(
  154. dispatcher,
  155. async move {
  156. let (old, new) = match options.and_then(|o| o.dir) {
  157. Some(dir) => (
  158. resolve_path(old_path, Some(dir.clone()))?,
  159. resolve_path(new_path, Some(dir))?,
  160. ),
  161. None => (old_path, new_path),
  162. };
  163. fs::rename(old, new).map_err(crate::Error::Io)
  164. },
  165. callback,
  166. error,
  167. )
  168. .await;
  169. }
  170. /// Writes a text file.
  171. #[cfg(write_file)]
  172. pub async fn write_file<D: ApplicationDispatcherExt>(
  173. dispatcher: &mut D,
  174. path: PathBuf,
  175. contents: String,
  176. options: Option<FileOperationOptions>,
  177. callback: String,
  178. error: String,
  179. ) {
  180. crate::execute_promise(
  181. dispatcher,
  182. async move {
  183. File::create(resolve_path(path, options.and_then(|o| o.dir))?)
  184. .map_err(crate::Error::Io)
  185. .and_then(|mut f| f.write_all(contents.as_bytes()).map_err(|err| err.into()))?;
  186. crate::Result::Ok(())
  187. },
  188. callback,
  189. error,
  190. )
  191. .await;
  192. }
  193. /// Writes a binary file.
  194. #[cfg(write_binary_file)]
  195. pub async fn write_binary_file<D: ApplicationDispatcherExt>(
  196. dispatcher: &mut D,
  197. path: PathBuf,
  198. contents: String,
  199. options: Option<FileOperationOptions>,
  200. callback: String,
  201. error: String,
  202. ) {
  203. crate::execute_promise(
  204. dispatcher,
  205. async move {
  206. base64::decode(contents)
  207. .map_err(crate::Error::Base64Decode)
  208. .and_then(|c| {
  209. File::create(resolve_path(path, options.and_then(|o| o.dir))?)
  210. .map_err(|e| e.into())
  211. .and_then(|mut f| f.write_all(&c).map_err(|err| err.into()))
  212. })?;
  213. crate::Result::Ok(())
  214. },
  215. callback,
  216. error,
  217. )
  218. .await;
  219. }
  220. /// Reads a text file.
  221. #[cfg(read_text_file)]
  222. pub async fn read_text_file<D: ApplicationDispatcherExt>(
  223. dispatcher: &mut D,
  224. path: PathBuf,
  225. options: Option<FileOperationOptions>,
  226. callback: String,
  227. error: String,
  228. ) {
  229. crate::execute_promise(
  230. dispatcher,
  231. async move {
  232. file::read_string(resolve_path(path, options.and_then(|o| o.dir))?)
  233. .map_err(crate::Error::FailedToExecuteApi)
  234. },
  235. callback,
  236. error,
  237. )
  238. .await;
  239. }
  240. /// Reads a binary file.
  241. #[cfg(read_binary_file)]
  242. pub async fn read_binary_file<D: ApplicationDispatcherExt>(
  243. dispatcher: &mut D,
  244. path: PathBuf,
  245. options: Option<FileOperationOptions>,
  246. callback: String,
  247. error: String,
  248. ) {
  249. crate::execute_promise(
  250. dispatcher,
  251. async move {
  252. file::read_binary(resolve_path(path, options.and_then(|o| o.dir))?)
  253. .map_err(crate::Error::FailedToExecuteApi)
  254. },
  255. callback,
  256. error,
  257. )
  258. .await;
  259. }
  260. // test webview functionality.
  261. #[cfg(test)]
  262. mod test {
  263. // use super::*;
  264. // use web_view::*;
  265. // create a makeshift webview
  266. // fn create_test_webview() -> crate::Result<WebView<'static, ()>> {
  267. // // basic html set into webview
  268. // let content = r#"<html><head></head><body></body></html>"#;
  269. // Ok(
  270. // // use webview builder to create simple webview
  271. // WebViewBuilder::new()
  272. // .title("test")
  273. // .size(800, 800)
  274. // .resizable(true)
  275. // .debug(true)
  276. // .user_data(())
  277. // .invoke_handler(|_wv, _arg| Ok(()))
  278. // .content(Content::Html(content))
  279. // .build()?,
  280. // )
  281. // }
  282. /* #[test]
  283. #[cfg(not(any(target_os = "linux", target_os = "macos")))]
  284. // test the file_write functionality
  285. fn test_write_to_file() -> crate::Result<()> {
  286. // import read_to_string and write to be able to manipulate the file.
  287. use std::fs::{read_to_string, write};
  288. // create the webview
  289. let mut webview = create_test_webview()?;
  290. // setup the contents and the path.
  291. let contents = String::from(r#"Write to the Test file"#);
  292. let path = String::from("test/fixture/test.txt");
  293. // clear the file by writing nothing to it.
  294. write(&path, "")?;
  295. //call write file with the path and contents.
  296. write_file(
  297. &mut dispatcher,
  298. path.clone(),
  299. contents.clone(),
  300. String::from(""),
  301. String::from(""),
  302. );
  303. // sleep the main thread to wait for the promise to execute.
  304. std::thread::sleep(std::time::Duration::from_millis(200));
  305. // read from the file.
  306. let data = read_to_string(path)?;
  307. // check that the file contents is equal to the expected contents.
  308. assert_eq!(data, contents);
  309. Ok(())
  310. } */
  311. }