12.React Native文件創建、查看、下載、上傳-react-native-fs

目錄

1.react-native-fs是什麼?

2.react-native-fs支持哪些功能?

3.react-native-fs如何使用?

4.react-native-fs功能介紹?

5.文件操作說明

5.1文件目錄說明

5.2文件創建

5.3文件刪除

5.4文件讀取

5.5文件上傳(支持IOS和Android)

5.6文件修改

5.7文件移動和複製

5.8文件是否存在

5.9創建文件夾

5.10文件下載


在移動端實際開發中難免會涉及涉及緩存:
a.AsyncStorage:一些簡單文本、用戶身份Token或者JSON文件等可以用AsyncStorage,類似h5的數據存儲LocalStorage;在 iOS 上,AsyncStorage在原生端的實現是把較小值存放在序列化的字典中,而把較大值寫入單獨的文件。在 Android 上,AsyncStorage會嘗試使用RocksDB,或退而選擇 SQLite。

可參考:

https://blog.csdn.net/ahou2468/article/details/88954215

b.Realm:Realm不是ORM(對象關係映射數據庫),也不是建立在sqlite之上。相反,我們爲移動應用程序開發人員構建了一個完整的數據庫,它使用動態映射到完整的自定義數據庫引擎(而不僅僅是一個鍵值存儲)的本機JavaScript對象。這允許我們在保持性能的同時提供一個簡單的API。使用Realm,您可以建模複雜的數據,鏈接圖形中的對象,以及組成高級查詢。

可參考:
 https://blog.csdn.net/ahou2468/article/details/94384048

c.文件存儲(react-native-fs):

實現了react native的訪問本地文件系統

主要介紹一下本地文件存儲(react-native-fs);

注意事項:

對於rn<0.57和/或gradle<3,您必須安裝react native fs的版本2.11.17!
對於rn>=0.57和/或gradle>=3,您必須時安裝react native fs的版本2.13.2!

1.react-native-fs是什麼?

實現了react native的訪問本地文件系統;

2.react-native-fs支持哪些功能?

支持文件的創建、刪除、查看、上傳、下載;

3.react-native-fs如何使用?

a.安裝(install)

npm install react-native-fs --save

b.鏈接(link)

react-native link react-native-fs

執行結果:

rnpm-install info Linking react-native-fs ios dependency 
rnpm-install info Platform 'ios' module react-native-fs has been successfully linked 
rnpm-install info Linking react-native-fs android dependency 
rnpm-install info Platform 'android' module react-native-fs has been successfully linked 

如果link失敗,或者link之後仍舊不能import,則考慮手動link,詳情查看官網教程,傳送門

4.react-native-fs功能介紹?

文件創建,修改,讀取,刪除,上傳,下載 ;

5.文件操作說明

5.1文件目錄說明

參數說明:

import RNFS from 'react-native-fs'

MainBundlePath (String) 主bundle目錄的絕對路徑; (在Android上不適合)
CachesDirectoryPath (String) 緩存目錄的絕對路徑;
ExternalCachesDirectoryPath (String) 外部緩存目錄的絕對路徑 (僅在Android上支持)
DocumentDirectoryPath (String) 文檔目錄的絕對路徑
TemporaryDirectoryPath (String) 臨時目錄的絕對路徑(返回到Android上的緩存目錄)
LibraryDirectoryPath (String) NSLibraryDirectory絕對路徑; (在iOS上支持)
ExternalDirectoryPath (String) 外部文件的絕對路徑,共享目錄(在android上支持)
ExternalStorageDirectoryPath (String) 外部存儲的絕對路徑,共享目錄 (在android上支持)

Android打印日誌:

MainBundlePath: undefined
CachesDirectoryPath: /data/user/0/com.helloworld/cache
ExternalCachesDirectoryPath: /storage/emulated/0/Android/data/com.helloworld/cache
DocumentDirectoryPath: /data/user/0/com.helloworld/files
ExternalDirectoryPath: /storage/emulated/0/Android/data/com.helloworld/files
ExternalStorageDirectoryPath: /storage/emulated/0
TemporaryDirectoryPath: /data/user/0/com.helloworld/cache
LibraryDirectoryPath: undefined
PicturesDirectoryPath: /storage/emulated/0/Pictures
FileProtectionKeys: undefined

android使用注意事項:

使用ExternalStorageDirectoryPath時,需要請求權限(在Android上)才能讀取和寫入外部存儲;在Android23版本以後需要申請權限;申請權限示例:https://facebook.github.io/react-native/docs/permissionsandroid

 

IOS的打印日誌

MainBundlePath: /Users/fandong/Library/Developer/CoreSimulator/Devices/2186A64F-
70D4-4BF2-A2F8-AE357F828D33/data/Containers/Bundle/Application/88D43269-12E3-4720-80D1-5618EBEF75DE/HelloWorld.app
CachesDirectoryPath: /Users/fandong/Library/Developer/CoreSimulator/Devices/2186A64F-70D4-4BF2-A2F8-
AE357F828D33/data/Containers/Data/Application/DA44823E-A4B6-4C4A-B020-294C75AF374D/Library/Caches
ExternalCachesDirectoryPath: undefined
DocumentDirectoryPath: /Users/fandong/Library/Developer/CoreSimulator/Devices/2186A64F-70D4-4BF2-A2F8-
AE357F828D33/data/Containers/Data/Application/DA44823E-A4B6-4C4A-B020-294C75AF374D/Documents
ExternalDirectoryPath: null
ExternalStorageDirectoryPath: null
TemporaryDirectoryPath: /Users/fandong/Library/Developer/CoreSimulator/Devices/2186A64F-70D4-4BF2-A2F8-
AE357F828D33/data/Containers/Data/Application/DA44823E-A4B6-4C4A-B020-294C75AF374D/tmp/
LibraryDirectoryPath: /Users/fandong/Library/Developer/CoreSimulator/Devices/2186A64F-70D4-4BF2-A2F8-
AE357F828D33/data/Containers/Data/Application/DA44823E-A4B6-4C4A-B020-
294C75AF374D/Library
PicturesDirectoryPath: undefined
FileProtectionKeys: undefined

這裏可以簡單瞭解一下ios的沙盒模型。
1、Documents 目錄:您應該將所有的應用程序數據文件寫入到這個目錄下。這個目錄用於存儲用戶數據。該路徑可通過配置實現iTunes共享文件。可被iTunes備份。
2、AppName.app 目錄:這是應用程序的程序包目錄,包含應用程序的本身。由於應用程序必須經過簽名,所以您在運行時不能對這個目錄中的內容進行修改,否則可能會使應用程序無法啓動。
3、Library 目錄:這個目錄下有兩個子目錄:
3.1 Preferences 目錄:包含應用程序的偏好設置文件。您不應該直接創建偏好設置文件,而是應該使用NSUserDefaults類來取得和設置應用程序的偏好.
3.2 Caches 目錄:用於存放應用程序專用的支持文件,保存應用程序再次啓動過程中需要的信息。
可創建子文件夾。可以用來放置您希望被備份但不希望被用戶看到的數據。該路徑下的文件夾,除Caches以外,都會被iTunes備份。
4、tmp 目錄:這個目錄用於存放臨時文件,保存應用程序再次啓動過程中不需要的信息。該路徑下的文件不會被iTunes備份。

5.2文件創建

let path = RNFS.DocumentDirectoryPath + '/test.txt';
        RNFS.writeFile(path, 'Lorem ipsum dolor sit amet', 'utf8')
            .then((success)=>{
                console.log('FILE WRITTEN'+' '+path);
            })
            .catch((err)=>{
                console.log(err.message);
            });

5.3文件刪除

//創建刪除路徑
        let delpath = RNFS.DocumentDirectoryPath + '/test.txt';
        //執行刪除
        RNFS.unlink(delpath)
            .then(()=>{
                console.log('FILE DELETED');
                //如果文件不存在,會拋出異常
            }).catch((err)=>{
                console.log(err.message);
            });

File does not exist

5.4文件讀取

 
//獲取文件列表和目錄
        RNFS.readDir(RNFS.DocumentDirectoryPath)
            .then((result)=>{
                console.log('GOT RESULT', result);
                // stat the second file,找到第二個 文件
                return Promise.all([RNFS.stat(result[1].path), result[1].path]);
            }).then((statResult)=>{
                /**
                 * stat
                 *return {
                    'path': filepath,
                    'ctime': new Date(result.ctime * 1000),
                    'mtime': new Date(result.mtime * 1000),
                    'size': result.size,
                    'mode': result.mode,
                    'originalFilepath': result.originalFilepath,
                    isFile: () => result.type === RNFSFileTypeRegular,
                    isDirectory: () => result.type === RNFSFileTypeDirectory,
      };
                 */
                // if we have a file, read it
                if(statResult[0].isFile()){ //返回的是數組,第一個是對象,第二個是文件
                    return RNFS.readFile(statResult[1], 'utf8');
                }
                // console.log(statResult[0].path);
                return 'no file';
            }).then((contents)=>{
                // log the file contents,輸出文件內容
                console.log(contents);
            }).catch((err) => {
                console.log(err.message, err.code);
            });

文件讀取方法:

讀取文件ReadDirItem定義:

type ReadDirItem = {
  ctime: date;     // The creation date of the file (iOS only)
  mtime: date;     // The last modified date of the file
  name: string;     // The name of the item
  path: string;     // The absolute path to the item
  size: string;     // Size in bytes
  isFile: () => boolean;        // Is the file just a file?
  isDirectory: () => boolean;   // Is the file a directory?
};

a.readDir(dirpath: string): Promise<ReadDirItem[]>

讀取路徑下的內容。這必須是絕對路徑。使用下面路徑常量形成可用的文件路徑。

export const MainBundlePath: string
export const CachesDirectoryPath: string
export const ExternalCachesDirectoryPath: string
export const DocumentDirectoryPath: string
export const ExternalDirectoryPath: string
export const ExternalStorageDirectoryPath: string
export const TemporaryDirectoryPath: string
export const LibraryDirectoryPath: string
export const PicturesDirectoryPath: string
export const FileProtectionKeys: string

返回的Promise使用具有以下屬性的對象數組解析:

type ReadDirItem = {
  ctime: date;     // The creation date of the file (iOS only)
  mtime: date;     // The last modified date of the file
  name: string;     // The name of the item
  path: string;     // The absolute path to the item
  size: string;     // Size in bytes
  isFile: () => boolean;        // Is the file just a file?
  isDirectory: () => boolean;   // Is the file a directory?
};

b.readDirAssets(dirpath: string): Promise<ReadDirItem[]>(Android)

讀取android應用程序的assets文件夾中dirpath的內容。dirpath是從assets文件夾根目錄到文件的相對路徑。

c.readdir(dirpath: string): Promise<string[]>

返回目錄下的文件名數組:["movies.realm.management", "test.txt", "ReactNativeDevBundle.js", "movies.realm.lock", "movies.realm", "movies.realm.note"]

d.stat(filepath: string): Promise<StatResult>

在filepath查找文件信息。如果文件路徑鏈接到虛擬文件(例如android content uri),則可以使用原始路徑查找指向的文件路徑。Promise使用具有以下屬性的對象解析:

type StatResult = {
  path:            // The same as filepath argument
  ctime: date;     // The creation date of the file
  mtime: date;     // The last modified date of the file
  size: string;     // Size in bytes
  mode: number;     // UNIX file mode
  originalFilepath: string;    // ANDROID: In case of content uri this is the pointed file path, otherwise is the same as path
  isFile: () => boolean;        // Is the file just a file?
  isDirectory: () => boolean;   // Is the file a directory?
};

e.readFile(filepath: string, encoding?: string): Promise<string>

讀取路徑處的文件並返回內容。編碼可以是utf8(默認)、ascii、base64之一。使用base64讀取二進制文件。

注意如果讀取大文件,會等待比較久;

f.read(filepath: string, length = 0, position = 0, encodingOrOptions?: any): Promise<string>

從路徑處文件的給定位置讀取長度字節並返回內容。編碼可以是utf8(默認)、ascii、base64之一。使用base64讀取二進制文件。
注意:分段讀取大文件可以改善性能。

g.readFileAssets(filepath:string, encoding?: string): Promise<string>

讀取android應用程序的assets文件夾中路徑處的文件並返回內容。編碼可以是utf8(默認)、ascii、base64之一。使用base64讀取二進制文件。
file path是從assets文件夾根目錄到文件的相對路徑。
注:僅限Android。

h.readFileRes(filename:string, encoding?: string): Promise<string>

讀取android應用的res文件夾中名爲filename的文件並返回內容。res/drawable用作圖像文件的父文件夾,res/raw用於其他所有文件。編碼可以是utf8(默認)、ascii、base64之一。使用base64讀取二進制文件。
注:僅限Android。

5.5文件上傳(支持IOS和Android)

// require the module,導入react-native-fs庫
var RNFS = require('react-native-fs');

var uploadUrl = 'http://requestb.in/XXXXXXX';  // For testing purposes, go to http://requestb.in/ and create your own link,測試上傳路徑
// create an array of objects of the files you want to upload
// 創建一個想要上傳文件的數組
var files = [
  {
    name: 'test1',
    filename: 'test1.w4a',
    filepath: RNFS.DocumentDirectoryPath + '/test1.w4a',
    filetype: 'audio/x-m4a'
  }, {
    name: 'test2',
    filename: 'test2.w4a',
    filepath: RNFS.DocumentDirectoryPath + '/test2.w4a',
    filetype: 'audio/x-m4a'
  }
];
//上傳開始回調
var uploadBegin = (response) => {
  var jobId = response.jobId;
  console.log('UPLOAD HAS BEGUN! JobId: ' + jobId);
};
//上傳進度回調
var uploadProgress = (response) => {
  var percentage = Math.floor((response.totalBytesSent/response.totalBytesExpectedToSend) * 100);
  console.log('UPLOAD IS ' + percentage + '% DONE!');
};

// upload files
//執行文件上傳
RNFS.uploadFiles({
  toUrl: uploadUrl,//文件上傳路徑
  files: files,    //上傳的文件數組
  method: 'POST',    //HTTP請求方法
  headers: {
    'Accept': 'application/json',    //請求header
  },
  fields: {
    'hello': 'world',
  },
  begin: uploadBegin,    //上傳開始回調
  progress: uploadProgress    //上傳進度回調
}).promise.then((response) => {//HTTP response響應
    if (response.statusCode == 200) {
      console.log('FILES UPLOADED!'); // response.statusCode狀態碼, response.headers響應header, response.body 響應body
    } else {
      console.log('SERVER ERROR');
    }
  })
  .catch((err) => {    //HTTP請求異常
    if(err.description === "cancelled") {
      // cancelled by user
    }
    console.log(err);
  });

5.6文件修改

a.writeFile(filepath: string, contents: string, encoding?: string): Promise<void>

將內容寫入到指定filepath下文件。編碼可以是utf8(默認)、ascii、base64之一。選項可以接受指定文件屬性的對象,如模式等。

b.appendFile(filepath: string, contents: string, encoding?: string): Promise<void>

將內容追加到filepath。編碼可以是utf8(默認)、ascii、base64之一。

c.write(filepath: string, contents: string, position?: number, encoding?: string): Promise<void>

在給定的隨機訪問位置將內容寫入filepath。當位置未定義或-1時,內容將附加到文件末尾。編碼可以是utf8(默認)、ascii、base64之一。

5.7文件移動和複製

a.moveFile(filepath: string, destPath: string): Promise<void>

移動文件到指定目錄;

b.copyFile(filepath: string, destPath: string): Promise<void>

複製文件到指定路徑 ;

更多複製文件操作方法參考:https://github.com/itinance/react-native-fs

5.8文件是否存在

a.exists(filepath: string): Promise<boolean>

檢測指定路徑下文件是否存在;

更多檢測文件是否存在操作方法參考:https://github.com/itinance/react-native-fs

5.9創建文件夾

a.mkdir(filepath: string, options?: MkdirOptions): Promise<void>

type MkdirOptions = {
  NSURLIsExcludedFromBackupKey?: boolean; // iOS only
};

在filepath創建一個目錄。自動創建父級,如果已經存在則不拋出(類似於linux mkdir-p)。
(僅限iOS):可以提供nsurlisexcludedfrombackupkey屬性以在iOS平臺上設置此屬性。蘋果將拒絕存儲沒有此屬性的離線緩存數據的應用程序。

5.10文件下載

a.文件下載

downloadFile(options: DownloadFileOptions): { jobId: number, promise: Promise<DownloadResult> }

DownloadFileOptions

type DownloadFileOptions = {
  fromUrl: string;          // 下載文件的url
  toFile: string;           // 本地保存文件的路徑URL
  headers?: Headers;        // 傳遞給服務器的請求header
  background?: boolean;     // 進入後臺後繼續下載(在iOS上支持)
  discretionary?: boolean;  // 允許操作系統控制下載的時間和速度,以提高感知性能 (在iOS上支持)
  cacheable?: boolean;      // 下載是否可以存儲在共享的nsurlcache中(在iOS上支持,默認爲true)
  progressDivider?: number;
  begin?: (res: DownloadBeginCallbackResult) => void;
  progress?: (res: DownloadProgressCallbackResult) => void;
  resumable?: () => void;    // 僅僅在IOS上支持
  connectionTimeout?: number // 僅僅在Android上支持
  readTimeout?: number       // 在IOS和Android上都支持
};

DownloadResult

type DownloadResult = {
  jobId: number;          // The download job ID, required if one wishes to cancel
 the download. See `stopDownload`.(生成的文件標識ID)
  statusCode: number;     // HTTP狀態code
  bytesWritten: number;   // 被寫入文件字節數量 
};

從options.fromUrl下載文件到options.toFile。將覆蓋任何以前存在的文件。

如果提供了options.begin,則當接收到頭並傳遞具有以下屬性的單個參數時,將在下載開始時調用它一次:

type DownloadBeginCallbackResult = {
  jobId: number;          // 下載文件ID, 當取消下載時需要用到文件ID. 見 `stopDownload`.
  statusCode: number;     // HTTP狀態碼
  contentLength: number;  // 實際下載文件大小
  headers: Headers;       // 來自於服務器HTTP的headers
};

如果提供了options.progress,則將連續調用它,並傳遞具有以下屬性的單個參數:

type DownloadProgressCallbackResult = {
  jobId: number;          // 下載文件ID, 當取消下載時需要用到文件ID. 見 `stopDownload`.
  contentLength: number;  //下載資源的文件大小
  bytesWritten: number;   // 到目前爲止被寫入文件字節大小
};

如果提供了options.progressdivider,它將返回被progressdivider劃分的進度事件。

例如,如果progressdivider=10,您將只收到10個進度值回調:0、10、20、30、40、50、60、70、80、90、100使用它解決性能問題。如果progressdivider=0,則將接收所有progresscallback調用,默認值爲0。

(僅限iOS):options.background(boolean)-當應用程序未聚焦時是否繼續下載(默認值:false)。此選項當前僅適用於iOS,請參閱後臺下載教程(iOS)(https://github.com/itinance/react-native-fs#background-downloads-tutorial-ios)部分。

(僅限iOS):如果提供了options.resumable,則將在下載停止時調用它,並且可以使用resumedownload()繼續。

b.停止文件下載

stopDownload(jobId: number): void

通過job ID中斷下載的文件 ,已下載的文件會保留在文件系統中;

c.重啓繼續下載

(僅限iOS) resumeDownload(jobId: number): void

通過job ID重啓文件下載;

d.檢測是否重啓繼續下載中

(iOS only) resumeDownload(jobId: number): void

檢查具有此ID的下載作業是否可以使用resumeDownload()恢復。

if (await RNFS.isResumable(jobId) {
    RNFS.resumeDownload(jobId)
}

e.監聽文件是否下載完成

(iOS only) completeHandlerIOS(jobId: number): void

要在使用後臺下載時使用,請告訴iOS您已完成對已完成下載的處理。

 

參考:

https://github.com/itinance/react-native-fs#background-downloads-tutorial-ios

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章