@umituz/react-native-filesystem 2.1.18 → 2.1.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@ import { downloadFile } from "./download.service";
|
|
|
11
11
|
import { clearCache, getDirectorySize } from "./cache.service";
|
|
12
12
|
import { generateFilePath } from "./file-path.service";
|
|
13
13
|
import { FileUtils } from "../../domain/entities/File";
|
|
14
|
-
import type { FileOperationResult } from "../../domain/entities/File";
|
|
14
|
+
import type { FileEncoding, DirectoryType, FileOperationResult } from "../../domain/entities/File";
|
|
15
15
|
|
|
16
16
|
export class FileSystemService {
|
|
17
17
|
static readFile = readFile;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Download Service
|
|
3
|
-
* Single Responsibility: Handle file download operations
|
|
4
3
|
*/
|
|
5
4
|
|
|
6
5
|
import { File, Paths, Directory } from "expo-file-system";
|
|
@@ -8,65 +7,40 @@ import type { FileOperationResult } from "../../domain/entities/File";
|
|
|
8
7
|
import { FileUtils } from "../../domain/entities/File";
|
|
9
8
|
import type { DownloadProgressCallback, DownloadWithProgressResult } from "./download.types";
|
|
10
9
|
|
|
11
|
-
const hashUrl = (url: string)
|
|
10
|
+
const hashUrl = (url: string) => {
|
|
12
11
|
let hash = 0;
|
|
13
12
|
for (let i = 0; i < url.length; i++) hash = ((hash << 5) - hash + url.charCodeAt(i)) | 0;
|
|
14
13
|
return Math.abs(hash).toString(36);
|
|
15
14
|
};
|
|
16
15
|
|
|
17
|
-
const getExt = (url: string)
|
|
16
|
+
const getExt = (url: string) => {
|
|
18
17
|
const ext = url.split("?")[0].split(".").pop()?.toLowerCase() || "mp4";
|
|
19
18
|
return ["mp4", "mov", "m4v", "webm", "jpg", "png", "pdf"].includes(ext) ? ext : "mp4";
|
|
20
19
|
};
|
|
21
20
|
|
|
22
|
-
const getCacheUri = (url: string, dir: string)
|
|
23
|
-
return FileUtils.joinPaths(dir, `cached_${hashUrl(url)}.${getExt(url)}`);
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
interface DownloadError extends Error {
|
|
27
|
-
message: string;
|
|
28
|
-
}
|
|
21
|
+
const getCacheUri = (url: string, dir: string) => FileUtils.joinPaths(dir, `cached_${hashUrl(url)}.${getExt(url)}`);
|
|
29
22
|
|
|
30
23
|
export async function downloadFile(url: string, dest?: string): Promise<FileOperationResult> {
|
|
31
24
|
try {
|
|
32
|
-
const destination = dest
|
|
33
|
-
? new File(dest)
|
|
34
|
-
: new File(Paths.document, FileUtils.generateUniqueFilename("download"));
|
|
25
|
+
const destination = dest ? new File(dest) : new File(Paths.document, FileUtils.generateUniqueFilename("download"));
|
|
35
26
|
const res = await File.downloadFileAsync(url, destination, { idempotent: true });
|
|
36
27
|
return { success: true, uri: res.uri };
|
|
37
|
-
} catch (
|
|
38
|
-
const downloadError = error as DownloadError;
|
|
39
|
-
return { success: false, error: downloadError.message || "Unknown error" };
|
|
40
|
-
}
|
|
28
|
+
} catch (e: any) { return { success: false, error: e.message }; }
|
|
41
29
|
}
|
|
42
30
|
|
|
43
|
-
export async function downloadFileWithProgress(
|
|
44
|
-
url: string,
|
|
45
|
-
cacheDir: string,
|
|
46
|
-
onProgress?: DownloadProgressCallback,
|
|
47
|
-
): Promise<DownloadWithProgressResult> {
|
|
31
|
+
export async function downloadFileWithProgress(url: string, cacheDir: string, onProgress?: DownloadProgressCallback): Promise<DownloadWithProgressResult> {
|
|
48
32
|
try {
|
|
49
33
|
const dir = new Directory(cacheDir);
|
|
50
|
-
if (!dir.exists) {
|
|
51
|
-
dir.create({ intermediates: true, idempotent: true });
|
|
52
|
-
}
|
|
34
|
+
if (!dir.exists) dir.create({ intermediates: true, idempotent: true });
|
|
53
35
|
|
|
54
36
|
const destUri = getCacheUri(url, cacheDir);
|
|
55
|
-
|
|
56
|
-
if (cachedFile.exists) {
|
|
57
|
-
return { success: true, uri: destUri, fromCache: true };
|
|
58
|
-
}
|
|
37
|
+
if (new File(destUri).exists) return { success: true, uri: destUri, fromCache: true };
|
|
59
38
|
|
|
60
39
|
const response = await fetch(url);
|
|
61
|
-
if (!response.ok) {
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
|
|
40
|
+
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
41
|
+
|
|
65
42
|
const totalBytes = parseInt(response.headers.get("content-length") || "0", 10);
|
|
66
|
-
if (!response.body) {
|
|
67
|
-
const downloadResult = await downloadFile(url, destUri);
|
|
68
|
-
return { ...downloadResult, fromCache: false };
|
|
69
|
-
}
|
|
43
|
+
if (!response.body) return { ...(await downloadFile(url, destUri)), fromCache: false };
|
|
70
44
|
|
|
71
45
|
const reader = response.body.getReader();
|
|
72
46
|
const chunks: Uint8Array[] = [];
|
|
@@ -77,39 +51,22 @@ export async function downloadFileWithProgress(
|
|
|
77
51
|
if (done) break;
|
|
78
52
|
chunks.push(value);
|
|
79
53
|
received += value.length;
|
|
80
|
-
onProgress?.({
|
|
81
|
-
totalBytesWritten: received,
|
|
82
|
-
totalBytesExpectedToWrite: totalBytes || received,
|
|
83
|
-
});
|
|
54
|
+
onProgress?.({ totalBytesWritten: received, totalBytesExpectedToWrite: totalBytes || received });
|
|
84
55
|
}
|
|
85
56
|
|
|
86
57
|
const all = new Uint8Array(received);
|
|
87
58
|
let pos = 0;
|
|
88
|
-
for (const
|
|
89
|
-
all.set(chunk, pos);
|
|
90
|
-
pos += chunk.length;
|
|
91
|
-
}
|
|
59
|
+
for (const c of chunks) { all.set(c, pos); pos += c.length; }
|
|
92
60
|
new File(destUri).write(all);
|
|
93
61
|
|
|
94
62
|
return { success: true, uri: destUri, fromCache: false };
|
|
95
|
-
} catch (
|
|
96
|
-
const downloadError = error as DownloadError;
|
|
97
|
-
return { success: false, error: downloadError.message || "Unknown error" };
|
|
98
|
-
}
|
|
63
|
+
} catch (e: any) { return { success: false, error: e.message }; }
|
|
99
64
|
}
|
|
100
65
|
|
|
101
|
-
export const isUrlCached = (url: string, dir: string)
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
return isUrlCached(url, dir) ? getCacheUri(url, dir) : null;
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
export const deleteCachedFile = (url: string, dir: string): boolean => {
|
|
110
|
-
const file = new File(getCacheUri(url, dir));
|
|
111
|
-
if (file.exists) {
|
|
112
|
-
file.delete();
|
|
113
|
-
}
|
|
66
|
+
export const isUrlCached = (url: string, dir: string) => new File(getCacheUri(url, dir)).exists;
|
|
67
|
+
export const getCachedFileUri = (url: string, dir: string) => isUrlCached(url, dir) ? getCacheUri(url, dir) : null;
|
|
68
|
+
export const deleteCachedFile = (url: string, dir: string) => {
|
|
69
|
+
const f = new File(getCacheUri(url, dir));
|
|
70
|
+
if (f.exists) f.delete();
|
|
114
71
|
return true;
|
|
115
72
|
};
|