在 Reacvt-Native 的圖片下載上,有蠻多三方元件已經整合封裝,我們這裡來簡單介紹一下 RNFS 的使用
下載
首先貼上程式碼:
// 圖片
let downloadDest;
if (Platform.OS === 'ios') {
// iOS路徑
downloadDest = `${RNFS.DocumentDirectoryPath}/${((Math.random() * 1000000) | 0)}.jpg`;
} else {
// 安卓存在掛載的外接儲存上
downloadDest = `${RNFS.ExternalDirectoryPath}/${((Math.random() * 1000000) | 0)}.jpg`;
}
let formUrl = imageUrl;
// 判斷有沒有這些字首,沒有的話下載會失敗
if (formUrl.indexOf("https://") != -1 || formUrl.indexOf("http://") != -1) {
} else {
formUrl = 'http://' + formUrl;
}
console.log('下載的formUrl===', formUrl)
const options = {
fromUrl: formUrl,
toFile: downloadDest,
};
try {
const ret = RNFS.downloadFile(options);
ret.promise.then(res => {
// 下載成功的回撥,例如儲存圖片
successCallBack('file://' + downloadDest)
}).catch(err => {
console.log('下載圖片錯誤,錯誤提示:', err);
});
}
catch (error) {
console.log('下載失敗', error);
}
複製程式碼
分析
首先使用 RNFS 下載圖片,流程是 設定圖片儲存路徑以及名稱 -> 判斷圖片是否為正常的連結(是否包含http/https開頭,沒有的話下載會失敗!)-> 配置必要的下載引數 -> 在回撥中實現對應邏輯
然後我們就開始從第一步開始說起,
設定圖片儲存路徑以及名稱
因為 iOS 跟安卓端路徑存在差異,因此需要分別對其設定相應路徑;
iOS 路徑使用 RNFS.DocumentDirectoryPath即獲取當前沙盒路徑,安卓端使用 RNFS.ExternalDirectoryPath。
對於圖片的命名,在這邊為了防止出現重名的情況,我們生成 UDID 來做圖片唯一識別,生成方式也很簡單:
export function getUUID(){
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0,
v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
}).toUpperCase();
}
複製程式碼
合起來圖片路徑就可以根據系統分別為:
if (Platform.OS === 'ios') {
// iOS路徑
downloadDest = `${RNFS.DocumentDirectoryPath}/${( getUUID())}.jpg`;
} else {
// 安卓存在掛載的外接儲存上
downloadDest = `${RNFS.ExternalDirectoryPath}/${( getUUID())}.jpg`;
}
複製程式碼
判斷圖片是否為正常的連結
使用 RNFS 下載圖片預設不支援沒有包含http/https開頭的,因此我們需要對其連結做一個判斷:
let formUrl = imageUrl;
// 判斷有沒有這些字首,沒有的話下載會失敗
if (formUrl.indexOf("https://") != -1 || formUrl.indexOf("http://") != -1) {
} else {
formUrl = 'http://' + formUrl;
}
複製程式碼
這樣就不會有問題了~
配置必要的下載引數
目前有以下這些引數,不過對我們來說只需要配置幾個必要的即可
type DownloadFileOptions = {
fromUrl: string; // 下載地址(必要)
toFile: string; // 下載到本地的路徑(必要)
headers?: Headers; // 通過伺服器的頭部資訊
background?: boolean; // 是否允許在後臺下載(只支援 iOS)
discretionary?: boolean; // 是否允許設定下載的時間和速度 (只支援 iOS)
cacheable?: boolean; // 是否允許 NSURLCache 獲取快取內容,預設允許(只支援 iOS)
progressDivider?: number; // 設定下載進度回撥的次數,比如設定 progressDivider = 5,那在進度回撥中回回撥5次,分別為:0,20,40,60,80,100,下載完成100的回撥預設存在
begin?: (res: DownloadBeginCallbackResult) => void;//開始下載
progress?: (res: DownloadProgressCallbackResult) => void;///下載進度
resumable?: () => void; // 斷點續傳(只支援 iOS)
connectionTimeout?: number // 設定連結超時時間(只支援安卓)
readTimeout?: number // 設定讀取資料超時時間,兩個端都是通用的
};
複製程式碼
如果只是簡簡單單想要下圖片的話,我們們只需要用前兩個就ok了~
const options = {
fromUrl: formUrl,
toFile: downloadDest,
};
//開始下載
const ret = RNFS.downloadFile(options);
複製程式碼
在回撥中實現對應邏輯
接著下載成功後,圖片儲存的路徑就是我們之前設定的檔案路徑,然後還需要在前面新增上 file:// 才能檢視圖片
try {
ret.promise.then(res => {
// 下載成功的回撥,例如儲存圖片
successCallBack('file://' + downloadDest)
}).catch(err => {
console.log('下載圖片錯誤,錯誤提示:', err);
});
}
catch (error) {
console.log('下載失敗', error);
}
複製程式碼
拷貝
拷貝功能使用起來就比較簡單,不過需要注意的是使用 RNFS 拷貝圖片之後,其實嚴格意義上說這個是剪下,並且需要重新對圖片命名;
首先,設定拷貝檔案的路徑,也是按照上面的方法:
let imageUrl =Platform.OS === 'ios'?('file://'+ `${RNFS.DocumentDirectoryPath}/${(getUUID())}.jpg`)
:('file://'+ `${RNFS.ExternalDirectoryPath}/${(getUUID())}.jpg`);
複製程式碼
接著呼叫拷貝的方法
RNFS.copyFile(url,imageUrl)
.then(()=>{
console.log('copy成功~',imageUrl)
})
.catch((error)=>{
LWToast.hide()
console.log('error:',error)
});
複製程式碼
url 為原圖片路徑,這裡還有一個地方值得注意的是,原圖片如果是把路徑做了持久化儲存,在第二次開啟 app 的時候,你會發現再次開啟圖片時是無法獲取到圖片的,對於 iOS 來說,因為 app 是在沙盒中執行,而每次執行的沙盒地址不一樣,因此我們只需要對圖片名稱做持久化儲存即可,然後通過 RNFS.DocumentDirectoryPath 這個方法來拼接真實路徑就可以了。