使用第三方庫react-native-fs
代碼如下:
import RNFS from "react-native-fs";
import { I18n } from "../lang";
import { Tools } from "../utils";
import { Platform } from "react-native";
/**
* 下載文件
*
* 測試代碼:
* const res = await downloadBusiness.downloadDocument({
fileUrl: "https://github.com/goweii/TestUrl/raw/master/AndroidKeyMd5.pdf",
fileName: "contract.pdf",
});
if (res.success) {
console.log(res.filePath);
Tools.info("文件下載成功,路徑:" + res.filePath)
}
*
*/
class DownloadBusiness {
normalizeUrl = (url) => {
if (Tools.isEmptyStr(url)) {
return "";
}
try {
return encodeURI(String(url).trim());
} catch (error) {
return String(url).trim();
}
}
getFileExt = (fileUrl, defaultExt = "pdf") => {
try {
const pureUrl = String(fileUrl ?? "").split("?")[0];
const ext = pureUrl.substring(pureUrl.lastIndexOf(".") + 1).trim();
if (!ext || ext.includes("/") || ext.length > 10) {
return defaultExt;
}
return ext;
} catch (error) {
return defaultExt;
}
}
sanitizeFileName = (fileName) => {
if (Tools.isEmptyStr(fileName)) {
return "";
}
const cleanName = String(fileName).replace(/[\\/:*?"<>|]/g, "_").trim();
return cleanName;
}
getFileName = (fileUrl, fileName, defaultExt = "pdf") => {
const ext = this.getFileExt(fileUrl, defaultExt);
let finalName = this.sanitizeFileName(fileName);
if (Tools.isEmptyStr(finalName)) {
const pureUrl = String(fileUrl ?? "").split("?")[0];
const urlLast = pureUrl.split("/").pop();
let decodedName = urlLast ?? "";
try {
decodedName = decodeURIComponent(decodedName);
} catch (error) {
}
finalName = this.sanitizeFileName(decodedName);
}
if (Tools.isEmptyStr(finalName)) {
finalName = `document_${Date.now()}.${ext}`;
} else if (!finalName.includes(".")) {
finalName = `${finalName}.${ext}`;
}
return finalName;
}
getDownloadDir = async () => {
let dir = "";
if (Platform.OS == "ios") {
dir = `${RNFS.DocumentDirectoryPath}/downloads`;
} else {
dir = `${RNFS.ExternalDirectoryPath}/downloads`;
}
const exists = await RNFS.exists(dir);
if (!exists) {
await RNFS.mkdir(dir);
}
return dir;
}
removeFileIfExists = async (filePath) => {
const exists = await RNFS.exists(filePath);
if (exists) {
await RNFS.unlink(filePath);
}
}
/**
* 下載文檔到應(yīng)用本地目錄
* @param {{fileUrl: string, fileName?: string, defaultExt?: string, headers?: object, showLoading?: boolean, showToast?: boolean}} params
* @returns {Promise<{success: boolean, filePath?: string, fileName?: string, statusCode?: number, error?: any}>}
*/
downloadDocument = async (params = {}) => {
const {
fileUrl,
fileName,
defaultExt = "pdf",
headers = {},
showLoading = true,
showToast = true,
} = params;
if (Tools.isEmptyStr(fileUrl)) {
if (showToast) {
Tools.info(I18n.t("my.failed"));
}
return { success: false, error: "fileUrl is empty" };
}
if (showLoading) {
Tools.showDarktLoading();
}
try {
const requestUrl = this.normalizeUrl(fileUrl);
const finalName = this.getFileName(requestUrl, fileName, defaultExt);
const dir = await this.getDownloadDir();
const toFile = `${dir}/${finalName}`;
await this.removeFileIfExists(toFile);
const result = await RNFS.downloadFile({
fromUrl: requestUrl,
toFile,
headers,
}).promise;
if (result.statusCode >= 200 && result.statusCode < 300) {
if (showToast) {
Tools.info(I18n.t("my.success"));
}
return {
success: true,
filePath: toFile,
fileName: finalName,
statusCode: result.statusCode,
};
}
await this.removeFileIfExists(toFile);
if (showToast) {
Tools.info(I18n.t("my.saveFailed"));
}
return {
success: false,
statusCode: result.statusCode,
error: `download failed with status code ${result.statusCode}`,
};
} catch (error) {
console.log("====== DownloadBusiness.downloadDocument error ======", error);
if (showToast) {
Tools.info(I18n.t("my.saveFailed"));
}
return {
success: false,
error,
};
} finally {
if (showLoading) {
Tools.hideDarkLoading();
}
}
}
}
const downloadBusiness = new DownloadBusiness();
export default downloadBusiness;