Hbuilder打包H5開發的App讀取寫入手機本地文件


在平時開發的html頁面中,我們寫的Js是沒有讀取用戶電腦本地文件的權限的,這是出於瀏覽器運行時的安全考慮的,但在我們在使用h5打包app時,如果再像瀏覽器上讓用戶下載,上傳文件,就會使用戶的使用體驗遠不如電腦上操作,而且經常會有一些想要緩存本地的數據,cookies太小,滿足不了需求,所以就想到能不能有內容時,我能直接操作手機的存取,我使用的是hbuilder打包app的,所以到官網上找找,就找到了有一節專門關於io的介紹,研究了一下使用方法,所以特此記錄一下

本文所參考官方文檔 https://www.html5plus.org/doc/zh_cn/io.html 

先明確幾個主要對象及方法,這里與java里的對照來看,會java的朋友可能會更容易理解

 

requestFileSystem  請求本地文件系統對象的方法,獲取指定的文件系統,可通過type指定獲取文件系統的類型。 獲取指定的文件系統對象成功通過succesCB回調返回,失敗則通過errorCB返回。 

參數:

    •  type: ( Number ) 必選 本地文件系統常量
    • 可取plus.io下的常量,如plus.io.PRIVATE_DOC、plus.io.PUBLIC_DOCUMENTS等。
    • succesCB: ( FileSystemSuccessCallback ) 必選 請求文件系統成功的回調
    • errorCB: ( FileErrorCallback ) 可選 請求文件系統失敗的回調

注意,這里的type取值共4個,對應於不同的空間,也有不同的訪問權限限制,一定要注意區分,如果讀取或寫入文件時報錯時,記得檢查這個地方, 以下為原文

為了安全管理應用的資源目錄,規范對文件系統的操作,5+ API在系統應用目錄的基礎設計了應用沙盒目錄, 分為私有目錄和公共目錄兩種類型,私有目錄僅應用自身可以訪問,公共目錄在多應用環境時(如小程序SDK)所有應用都可訪問。

 

 

DirectoryEntry 文件系統中的目錄對象,用於管理特定的本地目錄或者文件,對應於java中可以理解為File對象,這是操作文件最基礎的對象,一個directoryEntry對象就對應於一個文件或文件夾

屬性:

    • isFile: 操作對象的是否為文件,DirectoryEntry對象固定其值為false
    • isDirectory: 操作對象是否為目錄,DirectoryEntry對象固定其值為true
    • name: 目錄操作對象的名稱,不包括路徑
    • fullPath: 目錄操作對象的完整路徑,文件系統的絕對路徑
    • fileSystem: 文件操作對象所屬的文件系統對象,參考FileSystem

方法:

 

FileEntry 文件系統中的文件對象,用於管理特定的本地文件,對應於java中可以理解為File對象

屬性:

    • isFile: 文件操作對象的是否為文件,FileEntry對象固定其值為true
    • isDirectory: 文件操作對象是否為目錄,FileEntry對象固定其值為false
    • name: 文件操作對象的名稱,不包括路徑
    • fullPath: 文件操作對象的完整路徑,文件系統的絕對路徑
    • fileSystem: 文件操作對象所屬的文件系統對象,參考FileSystem

方法:

    • getMetadata: 獲取文件的屬性信息
    • moveTo: 移動文件
    • copyTo: 拷貝文件
    • toURL: 獲取文件路徑轉換為URL地址
    • toLocalURL: 獲取文件路徑轉換為本地路徑URL地址
    • toRemoteURL: 獲取文件路徑轉換為網絡路徑URL地址
    • remove: 刪除文件
    • getParent: 獲取文件所屬的父目錄
    • createWriter: 獲取文件關聯的寫文件操作對象FileWriter
    • file: 獲取文件數據對象

 

FileReader 創建讀取文件對象,主要是文件讀取相關的操作,文件以文本或者Base64編碼的字符串形式讀出來,對應於java中可理解為InputStream

屬性:

    • readyState: 當前讀取文件所處的狀態
    • result: 已讀取文件的內容
    • error: 文件操作錯誤代碼

方法:

    • abort: 終止文件讀取操作
    • readAsDataURL: 以URL編碼格式讀取文件數據內容
    • readAsText: 以文本格式讀取文件數據內容

事件:

    • onloadstart: 讀取文件開始時的回調函數
    • onload: 讀取文件成功完成的回調函數
    • onabort: 取消讀取文件時的回調函數
    • onerror: 文件讀取操作失敗時調用的回調函數
    • onloadend: 文件讀取操作完成時的回調函數

 

FileWriter 文件系統中的寫文件對象,用於寫入文件內容,用戶注冊自己的事件監聽器來接收writestart、progress、write、writeend、error和abort事件,一個FileWriter對象是為單個文件的操作而創建,可以使用該對象多次對相應文件進行寫入操作。 FileWriter維護該文件的指針位置及長度屬性,這樣就可以尋找和寫入文件的任何地方。 默認情況下,FileWriter從文件的開頭開始寫入(將覆蓋現有數據),seek方法可設置文件操作指定位置,如fw.seek(fw.length-1)寫入操作就會從文件的末尾開始 ,對應於java中理解為OutputStream

屬性:

    • readyState: 當前寫入文件所處的狀態
    • length: 文件當前的長度,單位為字節
    • position: 文件當前操作的指針位置
    • error: 文件寫入操作錯誤代碼

方法:

    • abort: 終止文件寫入操作
    • seek: 定位文件操作位置
    • truncate: 按照指定長度截斷文件
    • write: 向文件中寫入數據

事件:

    • onwritestart: 寫入文件開始時的回調函數
    • onwrite: 寫入文件成功完成的回調函數
    • onabort: 取消寫入文件時的回調函數
    • onerror: 文件寫入操作失敗時調用的回調函數
    • onwriteend: 文件寫入操作完成時的回調函數

 

 

下面是讀寫文件的主要代碼及說明

1、獲取文件讀寫的基礎,FileEntry對象

 1     //讀取應用公共文檔目錄
 2     plus.io.requestFileSystem(plus.io.PUBLIC_DOCUMENTS, function(fs) {
 3         // 通過fs.root獲取DirectoryEntry對象進行操作,獲取文件操作的根目錄
 4         //這里的filePath即你要讀取的文件所在的相對路徑,可隨意定義,但不得是 _www開頭,因為_www開頭是應用私有資源目錄的專用,只有讀權限,不能寫入,寫入時會報錯
 5         var filePath = 'abc/haha/test.txt';
 6         var rootDirectoryEntry = fs.root;
 7         rootDirectoryEntry.getFile(filePath, {
 8             //這個參數的作用是 指示如果文件或目錄不存在時是否進行創建,默認值為false,設為true表示如果這個filePath下的test.txt文件不存在就創建,當然,如果存在就直接返回,不會創建
 9             create: true
10         }, function(fileEntry) {
11             //FileEntry對象獲取成功,對應就是test.txt文件了,可以接着進行相應的讀寫操作了
12             
13         }, function(e) {
14             console.log(e.message);
15         });
16     }, function(e) {
17         console.log(e.message);
18     });

 

2、在上一步獲取到文件操作對象FileEntry的基礎上,開始讀操作

 1     //獲取文件
 2     fileEntry.file(function (file) {
 3         //console.log(file.size + ' <--> ' + file.name);
 4         //創建一個文件讀取工具,在java中理解就是InputStream輸入流
 5         var fileReader = new plus.io.FileReader();
 6         //成功讀取到文件內容時的回調,其中evt.target.result就是文件中的文本內容
 7         fileReader.onloadend = function (evt) {
 8             console.log(evt.target.result);
 9         }
10         //文件讀取操作失敗時調用的回調函數
11         fileReader.onerror = function (e) {
12             console.log(e.message);
13         }
14         //將剛才請求到的文件以utf-8編碼,文本的形式讀出
15         fileReader.readAsText(file, 'utf-8');
16     });

 

3、還是以文件操作對象FileEntry為基礎,進行寫入文件的操作

 

 1     //通過fileEntry的createWriter創建輸出流,向文件寫入內容,對應java中的OutputStream
 2     fileEntry.createWriter(writer => {
 3         //文件寫入成功后的回調
 4         writer.onwrite = function(event) {
 5             //寫入成功
 6             console.log('寫入成功');
 7         }
 8         //文件寫入操作失敗時調用的回調函數
 9         writer.onerror = function(e) {
10             console.log(e.message);
11         }
12         //設置文件寫入的起點,writer.length就是上次文件里面內容的最后位置,這樣即將新的內容追加到文本最末尾,如果想覆蓋原先的內容,直接設置為0即可
13         var cursor =  writer.length;
14         writer.seek(cursor);
15         //將要寫入的文本dataStr寫入到文件中去
16         writer.write(dataStr);
17     }, function(e) {
18         console.log(e.message);
19     });

 

以上就是在Hbuilder中打包H5的App讀寫文件的主要代碼了及功能了

但是我們發現這樣寫會有無數的回調函數,不僅不好看,別人調用時也不好傳參,所以我們可以采用ES6的寫法加上Primse來封裝改造一下,讓這些方法看起來更加優雅一點

 1     getFileEntry(filePath) {
 2         return new Promise((resolve, reject) => {
 3             plus.io.requestFileSystem(plus.io.PUBLIC_DOCUMENTS, fs => {
 4                 fs.root.getFile(filePath, {create: true}, fileEntry => {
 5                     resolve(fileEntry);
 6                 }, e => {
 7                     reject(e)
 8                 });
 9             }, e => {
10                 reject(e)
11             });
12         })
13     },
14     readData(fileEntry) {
15         return new Promise((resolve, reject) => {
16             fileEntry.file(function (file) {
17                 let fileReader = new plus.io.FileReader();
18                 fileReader.onloadend = function (evt) {
19                     resolve(evt.target.result);
20                 }
21                 fileReader.onerror = function (e) {
22                     reject(e)
23                 }
24                 fileReader.readAsText(file, 'utf-8');
25             });
26         })
27     },
28     writeData(fileEntry, dataStr, cursorStart) {
29         return new Promise((resolve, reject) => {
30             fileEntry.createWriter(writer => {
31                 writer.onwrite = e => {
32                     resolve()
33                 }
34                 writer.onerror = e => {
35                     reject(e)
36                 }
37                 //設置文件寫入的起點
38                 let length = cursorStart != undefined ? cursorStart : writer.length;
39                 writer.seek(length);
40                 writer.write(dataStr);
41             }, e => {
42                 reject(e)
43             });
44         })
45     }

 

這樣在調用時,代碼就會非常簡潔了

讀取文件內容

 1     let filePath = '/abc/haha/test.json';
 2     this.getFileEntry(filePath)
 3     .then(fileEntry => {
 4         // fileEntry.remove();    //刪除文件
 5         return this.readData(fileEntry);
 6     }).then(fileText => {
 7         alert("文件內容:>>> " + fileText)
 8     }).catch(e => {
 9         alert('文件讀取失敗!')
10     })

 

寫入文件內容

1     let writeDataStr = 'Hello World!!!'
2     this.getFileEntry()
3     .then(fileEntry => {
4         return this.writeData(fileEntry, writeDataStr);
5     }).then(writer => {
6         alert('保存成功');    
7     }).catch(e => {
8         alert('保存失敗!')
9     })

OK ! 打完收工


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM