Support writing binary file to local disk (#580)

Co-authored-by: Lucas Fernandes Nogueira <lucasfernandesnog@gmail.com>
Co-authored-by: Lucas Fernandes Nogueira <lucas@tauri.studio>
This commit is contained in:
Ping Chen
2020-06-21 07:21:41 +09:00
committed by GitHub
parent 0f52af6c8f
commit 622e1d52d2
7 changed files with 153 additions and 3 deletions

View File

@@ -70,6 +70,7 @@ If you are interested in making a tauri-app, please visit the [documentation web
- [x] renameFile - rename a file
- [x] copyFile - copy a file to a new destination
- [x] writeFile - write file to local filesystem
- [x] writeBinaryFile - write binary file to local filesystem
- [x] readBinaryFile - read binary file from local filesystem
- [x] readTextFile - read text file from local filesystem

View File

@@ -39,6 +39,56 @@ function writeFile (file, options = {}) {
return tauri.writeFile(file, options)
}
const CHUNK_SIZE = 65536;
/**
* convert an Uint8Array to ascii string
*
* @param {Uint8Array} arr
* @return {String}
*/
function uint8ArrayToString(arr) {
if (arr.length < CHUNK_SIZE) {
return String.fromCharCode.apply(null, arr)
}
let result = ''
const arrLen = arr.length
for (let i = 0; i < arrLen; i++) {
const chunk = arr.subarray(i * CHUNK_SIZE, (i + 1) * CHUNK_SIZE)
result += String.fromCharCode.apply(null, chunk)
}
return result
}
/**
* convert an ArrayBuffer to base64 encoded string
*
* @param {ArrayBuffer} buffer
* @return {String}
*/
function arrayBufferToBase64(buffer) {
const str = uint8ArrayToString(new Uint8Array(buffer))
return btoa(str)
}
/**
* writes a binary file
*
* @param {Object} file
* @param {String} file.path path of the file
* @param {ArrayBuffer} file.contents contents of the file
* @param {Object} [options] configuration object
* @param {BaseDirectory} [options.dir] base directory
* @return {Promise<void>}
*/
function writeBinaryFile(file, options = {}) {
return tauri.writeBinaryFile({
...file,
contents: arrayBufferToBase64(file.contents)
}, options)
}
/**
* @typedef {Object} FileEntry
* @property {String} path
@@ -131,6 +181,7 @@ export {
readTextFile,
readBinaryFile,
writeFile,
writeBinaryFile,
readDir,
createDir,
removeDir,

View File

@@ -205,6 +205,28 @@ window.tauri = {
<% } %>
},
<% if (ctx.dev) { %>
/**
* @name writeBinaryFile
* @description Write a binary file to the Local Filesystem.
* Permissions based on the app's PID owner
* @param {Object} cfg
* @param {String} cfg.file
* @param {String|Binary} cfg.contents
*/
<% } %>
writeBinaryFile (cfg) {
<% if (tauri.whitelist.writeBinaryFile === true || tauri.whitelist.all === true) { %>
Object.freeze(cfg)
this.invoke({ cmd: 'writeBinaryFile', file: cfg.file, contents: cfg.contents })
<% } else { %>
<% if (ctx.dev) { %>
__whitelistWarning('writeBinaryFile')
<% } %>
return __reject
<% } %>
},
<% if (ctx.dev) { %>
/**
* @name listFiles

View File

@@ -43,7 +43,7 @@ switch (navigator.platform) {
case "Win32":
case "Win64":
break;
default:
default:
window.external = this
invoke = function (x) {
window.webkit.messageHandlers.external.postMessage(x);
@@ -320,6 +320,37 @@ switch (navigator.platform) {
<% } %>
},
<% if (ctx.dev) { %>
/**
* @name writeBinaryFile
* @description Write a binary file to the Local Filesystem.
* Permissions based on the app's PID owner
* @param {Object} cfg
* @param {String} cfg.file
* @param {String|Binary} cfg.contents
* @param {Object} [options]
* @param {BaseDirectory} [options.dir]
*/
<% } %>
writeBinaryFile: function writeBinaryFile(cfg, options) {
<% if (tauri.whitelist.writeBinaryFile === true || tauri.whitelist.all === true) { %>
if (_typeof(cfg) === 'object') {
Object.freeze(cfg);
}
return this.promisified({
cmd: 'writeBinaryFile',
file: cfg.file,
contents: cfg.contents,
options: options
});
<% } else { %>
<% if (ctx.dev) { %>
return __whitelistWarning('writeBinaryFile')
<% } %>
return __reject()
<% } %>
},
<% if (ctx.dev) { %>
/**
* @name readDir
@@ -343,8 +374,7 @@ switch (navigator.platform) {
<% if (ctx.dev) { %>
return __whitelistWarning('readDir')
<% } %>
return __reject()
<% } %>
<% } %>
},
<% if (ctx.dev) { %>

View File

@@ -52,6 +52,16 @@ pub(crate) fn handle<T: 'static>(webview: &mut WebView<'_, T>, arg: &str) -> cra
} => {
file_system::write_file(webview, file, contents, options, callback, error);
}
#[cfg(any(feature = "all-api", feature = "write-binary-file"))]
WriteBinaryFile {
file,
contents,
options,
callback,
error,
} => {
file_system::write_binary_file(webview, file, contents, options, callback, error);
}
#[cfg(any(feature = "all-api", feature = "read-dir"))]
ReadDir {
path,

View File

@@ -65,6 +65,14 @@ pub enum Cmd {
callback: String,
error: String,
},
#[cfg(any(feature = "all-api", feature = "write-binary-file"))]
WriteBinaryFile {
file: String,
contents: String,
options: Option<FileOperationOptions>,
callback: String,
error: String,
},
#[cfg(any(feature = "all-api", feature = "read-dir"))]
ReadDir {
path: String,

View File

@@ -194,6 +194,34 @@ pub fn write_file<T: 'static>(
);
}
pub fn write_binary_file<T: 'static>(
webview: &mut WebView<'_, T>,
file: String,
contents: String,
options: Option<FileOperationOptions>,
callback: String,
error: String,
) {
crate::execute_promise(
webview,
move || {
base64::decode(contents)
.map_err(|e| e.into())
.and_then(|c| {
File::create(resolve_path(file, options.and_then(|o| o.dir))?)
.map_err(|e| e.into())
.and_then(|mut f| {
f.write_all(&c)
.map_err(|err| err.into())
.map(|_| "".to_string())
})
})
},
callback,
error,
);
}
pub fn read_text_file<T: 'static>(
webview: &mut WebView<'_, T>,
path: String,