有一个需求是需要将本地上传的文件或者网络下载的文件存储到本地,并展示在前端页面上的。其实如果只是加载本地文件,然后展示还是挺简单的,可以看我的文章:tauri程序加载本地图片或者文件在前端页面展示-CSDN博客
要想实现上述需求,需要三个步骤,配置相应的文件和文件夹访问权限,然后将文件存储到软件的相应目录中,再从目录中加载这个资源并展示。
配置访问权限
如果你需要通过弹窗选择加载本地文件,需要配置dialog权限,存储文件需要配置存储目录权限fs下面的scope和path权限,想要加载文件并在前端页面可以访问,需要配置资产协议访问权限protocol。其中scope是你要存储文件到哪个路径下,assetScope是你要访问哪些路径下的资源。
"path": {"all": true},"fs": {"all": true,"readFile": true,"writeFile": true,"readDir": true,"copyFile": true,"createDir": true,"removeDir": true,"removeFile": true,"renameFile": true,"exists": true,"scope": ["$CACHE/PakePlus/*", "$APPDATA/*"]},"dialog": {"all": true,"ask": true,"confirm": true,"message": true,"open": true,"save": true},"protocol": {"all": true,"asset": true,"assetScope": ["$PICTURE", "$CACHE/*"]},
存储文件到本地
加载本地文件并存储到软件指定的文件夹中,这里需要读取到文件的内容,如果是图片文件,需要读为二进制内容,并进行存储。
import { writeBinaryFile, BaseDirectory } from '@tauri-apps/api/fs';
import { appDataDir } from '@tauri-apps/api/path';const saveImageToAppData = async (filePath) => {// 读取原始图片文件const response = await fetch(filePath);const imageBlob = await response.blob();const imageArrayBuffer = await imageBlob.arrayBuffer();const imageData = new Uint8Array(imageArrayBuffer);// 获取应用数据目录const appDataDirPath = await appDataDir();// 拼接文件保存路径const fileName = filePath.split('/').pop(); // 获取原始文件名const savePath = `${appDataDirPath}/${fileName}`;// 将图片保存到应用数据目录await writeBinaryFile(savePath, imageData, { dir: BaseDirectory.AppData });console.log(`Image saved to: ${savePath}`);return savePath;
}
或者使用前端的input标签选中文件拿到base64编码的文件,然后转为ArrayBuffer再进行存储:
<inputid="open"type="file"name="filename"style="display: none"@change="changeFile"/>// iconInput change
const changeFile = (event: any) => {// get base64 contentconst file = event.target.files[0] // 获取文件console.log('file---', file)if (file) {appForm.icon = file.nameconsole.log('file---', event.target.files)// appForm.icon = event.target.files.nameconst reader = new FileReader() // 创建FileReader对象reader.onload = function (e: any) {const base64String = e.target.result.split('base64,')[1] // 获取Base64编码console.log('base64String---', base64String) // 打印Base64编码内容// save image to datadirsaveImage(file.name, base64String)}reader.readAsDataURL(file) // 将文件读取为Base64}
}// save image file to datadir
const saveImage = async (fileName: string, base64: string) => {// base64 to arraybufferconst imageArrayBuffer = base64ToArrayBuffer(base64)// save fileconst imageData = new Uint8Array(imageArrayBuffer)// 获取应用数据目录const appDataPath = await resourceDir()console.log('appDataPath------', appDataPath)// 拼接文件保存路径const savePath = `${appDataPath}${fileName}`// 将图片保存到应用数据目录await writeBinaryFile(savePath, imageData, {dir: BaseDirectory.Cache,})console.log(`Image saved to: ${savePath}`)appForm.desc = savePathconst filePath = await join(appDataPath, fileName)console.log('filePath---', filePath)const assetUrl = convertFileSrc(filePath)console.log('assetUrl---', assetUrl)localImagePath.value = assetUrl
}// 将base64转换为ArrayBuffer
const base64ToArrayBuffer = (base64: string) => {// 创建一个新的 ArrayBufferconst binaryString = atob(base64)const len = binaryString.lengthconst arrayBuffer = new ArrayBuffer(len)const uint8Array = new Uint8Array(arrayBuffer)// 将二进制字符串中的字符逐个存入 Uint8Arrayfor (let i = 0; i < len; i++) {uint8Array[i] = binaryString.charCodeAt(i)}return arrayBuffer
}
加载文件为Url
读取保存的文件内容,并展示到页面上,需要拿到存储的路径,然后通过convertFileSrc这个api将文件路径转化为前端可以直接访问的文件:
const filePath = await join(appDataPath, fileName)console.log('filePath---', filePath)const assetUrl = convertFileSrc(filePath)console.log('assetUrl---', assetUrl)localImagePath.value = assetUrl
如果是图片文件,直接将url设置进去就可以了。
报错解决
1.Unhandled Promise Rejection: The `Path` module is not enabled. You must enable one of its APIs in the allowlist.
这是因为没有开启path路径访问权限: