溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Tauri打開本地文件錯誤怎么解決

發(fā)布時間:2023-04-15 14:13:09 來源:億速云 閱讀:166 作者:iii 欄目:開發(fā)技術(shù)

本篇內(nèi)容介紹了“Tauri打開本地文件錯誤怎么解決”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

    需求

    需求很簡單,就是打開本地圖片進(jìn)行展示,同時還要能拿到圖片在本地的絕對路徑。

    • 展示圖片

    • 拿到絕對路徑

    <input type="file" >存在的問題

    最先想到辦法,當(dāng)然是使用input元素,這是前端讀取本地文件的常規(guī)方案,而且我曾經(jīng)使用electron實現(xiàn)過一樣的功能,大致就是:

    <input type="file" id="file-selector" />
    document.getElementById("file-selector").addEventListener('change', e => {
        const files = e.target.files
        files.forEach(file => {
            const url = URL.createObjectURL(file)
            const path = file.path
        })
    })

    但遺憾的是,Tauri的File對象并沒有實現(xiàn)path這個屬性。

    出于安全考慮,瀏覽器并沒有提供File對象的絕對路徑,pathelectron自己提供的:electron/file-object.md at main &middot; electron/electron (github.com)。

    隨后,盡管想了各種辦法,比如引入file-selector之類的,但最終的結(jié)論是:input拿不到文件的絕對路徑。

    Dialog打開文件

    我在心里吐槽“Tauri果然是不如electron”之后,我決定去Github上搜一下issue,不出所料,不只我一個人遇到這個問題:

    Getting a real path of file type input &middot; Issue #87

    這里面給出了一個拿到文件絕對路徑的辦法,那就是使用Dialog

    首先在tauri.conf.json添加配置:

    "allowlist": {
        "dialog": {
            "all": false,
            "open": true
        }
    }

    然后

    import { open } from "@tauri/api/dialog"
    async handler(){
      let file = await open()
    }

    open方法會像input file一樣打開一個文件選擇框,返回文件的絕對路徑。

    如果想一次選擇多個文件,可以添加選項:

    let files = await open({ multiple: true })

    實際嘗試發(fā)現(xiàn),這樣確實能拿到文件的絕對路徑,但也只有絕對路徑。

    于是我就陷入了困境:通過input可以展示圖片,但拿不到絕對路徑,而dialog可以拿到絕對路徑,卻無法顯示圖片,因為前端無法直接通過一個本地的絕對路徑來展示圖片。

    怎么辦呢?

    fs讀取文件

    于是,我開始考慮使用Tauri提供的fs API,利用絕對路徑來讀取文件內(nèi)容,然后再轉(zhuǎn)換成Blob對象。

    配置tauri.conf.json

    "allowlist": {
        "dialog": {
            "all": false,
            "open": true
        },
        "fs": {
            "all": false,
            "readFile": true,
        }
    }

    讀取文件并轉(zhuǎn)換:

    import { readBinaryFile } from '@tauri-apps/api/fs';
    import { open } from "@tauri/api/dialog"
    async handler(){
      // 打開文件獲取絕對路徑
      let files = await open({ multiple: true })
      files.forEach(async filePath => {
          // 讀取二進(jìn)制文件
          const contents = await readBinaryFile(filePath)
          // 轉(zhuǎn)換為blob對象,然后轉(zhuǎn)換為url
          const blob = new Blob([contents])
          const url = URL.createObjectURL(blob)
      })
    }

    但是,正如我預(yù)期的那樣,這么做有嚴(yán)重的性能問題。

    經(jīng)簡單測試,打開100張圖片(每張400kb左右)需要好幾秒鐘才能完成,打開500張圖片更是花了約20秒才處理完畢。

    而如果使用input file,500張圖片只要一兩秒就能搞定。

    所以,雖然功能上已經(jīng)沒有問題,但性能問題無法忽視,看來還需要找找別的辦法。

    最終解決辦法

    經(jīng)過一整天的摸索,我最終找到了Tauri提供這個函數(shù):convertFileSrc,可以將一個絕對路徑轉(zhuǎn)換為類似于URL.createObjectURL那樣的URL。

    值得一提的是,這個函數(shù)和最常用的 invoke處于同一個模塊內(nèi),而且在Tauri的文檔中,convertFileSrc甚至位于invoke之前,但我卻一直沒有注意到它,一方面是因為,之前從沒有想過要使用絕對路徑來轉(zhuǎn)換URL,因為純前端是做不到這一點的;另一方面,由于思維慣性,前端打開本地文件往往都是用的input file,遇到這個問題我一直想的是如何從input事件著手,沒有去仔細(xì)看文檔&hellip;&hellip;這就是所謂的燈下黑嗎

    首先,配置tauri.conf.json

    {
        "allowlist": {
            "dialog": {
                "all": true,
                "open": true
            },
            "protocol": {
                "all": false,
                "asset": true,
                "assetScope": [
                    "$PICTURE"
                ]
            }
        },
        "security": {
            "csp": "default-src 'self'; img-src 'self'; asset: https://asset.localhost"
        }
    }

    然后

    import { convertFileSrc } from '@tauri-apps/api/tauri'
    import { open } from "@tauri/api/dialog"
    async handler(){
      let files = await open({ multiple: true })
      files.forEach(filePath =&gt; {
          const url = convertFileSrc(filePath)
      })
    }

    速度和HTML原生的input file差不多,雖然拿不到文件大小之類的信息,但至少我最需要的兩個需求可以實現(xiàn)了,只要有了絕對路徑,文件大小之類的可以交給Rust。

    “Tauri打開本地文件錯誤怎么解決”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI