xref: /MusicFree/src/utils/fileUtils.ts (revision e593fd4a6f831a1746f5c1616ab738bd2b30698a)
1cfa0fc07S猫头猫import pathConst from '@/constants/pathConst';
2cfa0fc07S猫头猫import FastImage from 'react-native-fast-image';
3740e3947S猫头猫import RNFS, {
4cfa0fc07S猫头猫    copyFile,
5cfa0fc07S猫头猫    downloadFile,
6cfa0fc07S猫头猫    exists,
7cfa0fc07S猫头猫    mkdir,
8cfa0fc07S猫头猫    PicturesDirectoryPath,
9cfa0fc07S猫头猫    readDir,
10cfa0fc07S猫头猫    unlink,
11cfa0fc07S猫头猫    writeFile,
12cfa0fc07S猫头猫} from 'react-native-fs';
13b882a19dS猫头猫import {errorLog} from './log';
14483fe585S猫头猫import path from 'path-browserify';
15d1f226e6S猫头猫
160c266394S猫头猫export const galleryBasePath = `${PicturesDirectoryPath}/MusicFree/`;
170c266394S猫头猫
18d1f226e6S猫头猫export async function saveToGallery(src: string) {
190c266394S猫头猫    const fileName = `${galleryBasePath}${Date.now()}.png`;
200c266394S猫头猫    if (!(await exists(galleryBasePath))) {
210c266394S猫头猫        await mkdir(galleryBasePath);
22d1f226e6S猫头猫    }
23cfa0fc07S猫头猫    if (await exists(src)) {
24d1f226e6S猫头猫        try {
25cfa0fc07S猫头猫            await copyFile(src, fileName);
26d1f226e6S猫头猫        } catch (e) {
27d1f226e6S猫头猫            console.log('... ', e);
28d1f226e6S猫头猫        }
29d1f226e6S猫头猫    }
30d1f226e6S猫头猫    if (src.startsWith('http')) {
31cfa0fc07S猫头猫        await downloadFile({
32d1f226e6S猫头猫            fromUrl: src,
33d1f226e6S猫头猫            toFile: fileName,
34d1f226e6S猫头猫            background: true,
35d1f226e6S猫头猫        });
36d1f226e6S猫头猫    }
37d1f226e6S猫头猫    if (src.startsWith('data')) {
38cfa0fc07S猫头猫        await writeFile(fileName, src);
39d1f226e6S猫头猫    }
40d1f226e6S猫头猫}
41ff8df87dS猫头猫
42cafdf1d5S猫头猫export function sizeFormatter(bytes: number | string) {
43cafdf1d5S猫头猫    if (typeof bytes === 'string') {
44cafdf1d5S猫头猫        return bytes;
45cafdf1d5S猫头猫    }
465589cdf3S猫头猫    if (bytes === 0) {
475589cdf3S猫头猫        return '0B';
485589cdf3S猫头猫    }
49ff8df87dS猫头猫    let k = 1024,
50ff8df87dS猫头猫        sizes = ['B', 'KB', 'MB', 'GB'],
51ff8df87dS猫头猫        i = Math.floor(Math.log(bytes) / Math.log(k));
52ff8df87dS猫头猫    return (bytes / Math.pow(k, i)).toFixed(1) + sizes[i];
53ff8df87dS猫头猫}
54be0a3650S猫头猫
55bae3deccS猫头猫export async function checkAndCreateDir(dirPath: string) {
56bae3deccS猫头猫    const filePath = dirPath;
57b882a19dS猫头猫    try {
58be0a3650S猫头猫        if (!(await exists(filePath))) {
59be0a3650S猫头猫            await mkdir(filePath);
60be0a3650S猫头猫        }
61b882a19dS猫头猫    } catch (e) {
62bae3deccS猫头猫        errorLog('无法初始化目录', {path: dirPath, e});
63b882a19dS猫头猫    }
64be0a3650S猫头猫}
65cfa0fc07S猫头猫
66bae3deccS猫头猫async function getFolderSize(dirPath: string): Promise<number> {
67cfa0fc07S猫头猫    let size = 0;
68cfa0fc07S猫头猫    try {
69bae3deccS猫头猫        const fns = await readDir(dirPath);
70cfa0fc07S猫头猫        for (let fn of fns) {
71cfa0fc07S猫头猫            if (fn.isFile()) {
72cfa0fc07S猫头猫                size += fn.size;
73cfa0fc07S猫头猫            }
74cfa0fc07S猫头猫            // todo: 可以改成并行 promise.all
75cfa0fc07S猫头猫            if (fn.isDirectory()) {
76cfa0fc07S猫头猫                size += await getFolderSize(fn.path);
77cfa0fc07S猫头猫            }
78cfa0fc07S猫头猫        }
79cfa0fc07S猫头猫    } catch {}
80cfa0fc07S猫头猫    return size;
81cfa0fc07S猫头猫}
82cfa0fc07S猫头猫
83cfa0fc07S猫头猫export async function getCacheSize(
84cfa0fc07S猫头猫    type: 'music' | 'lyric' | 'image',
85cfa0fc07S猫头猫): Promise<number> {
86cfa0fc07S猫头猫    if (type === 'music') {
87cfa0fc07S猫头猫        return getFolderSize(pathConst.musicCachePath);
88cfa0fc07S猫头猫    } else if (type === 'lyric') {
89cfa0fc07S猫头猫        return getFolderSize(pathConst.lrcCachePath);
90cfa0fc07S猫头猫    } else if (type === 'image') {
91cfa0fc07S猫头猫        return getFolderSize(pathConst.imageCachePath);
92cfa0fc07S猫头猫    }
93cfa0fc07S猫头猫    throw new Error();
94cfa0fc07S猫头猫}
95cfa0fc07S猫头猫
96cfa0fc07S猫头猫export async function clearCache(type: 'music' | 'lyric' | 'image') {
97cfa0fc07S猫头猫    if (type === 'music') {
98cfa0fc07S猫头猫        try {
99cfa0fc07S猫头猫            if (await exists(pathConst.musicCachePath)) {
100cfa0fc07S猫头猫                return unlink(pathConst.musicCachePath);
101cfa0fc07S猫头猫            }
102cfa0fc07S猫头猫        } catch {}
103cfa0fc07S猫头猫    } else if (type === 'lyric') {
104cfa0fc07S猫头猫        try {
105cfa0fc07S猫头猫            const lrcs = readDir(pathConst.lrcCachePath);
106cfa0fc07S猫头猫            return Promise.all((await lrcs).map(_ => unlink(_.path)));
107cfa0fc07S猫头猫        } catch {}
108cfa0fc07S猫头猫    } else if (type === 'image') {
109cfa0fc07S猫头猫        return FastImage.clearDiskCache();
110cfa0fc07S猫头猫    }
111cfa0fc07S猫头猫}
1126141fdfbS猫头猫
1136141fdfbS猫头猫export function addFileScheme(fileName: string) {
1146141fdfbS猫头猫    if (fileName.startsWith('/')) {
1156141fdfbS猫头猫        return `file://${fileName}`;
1166141fdfbS猫头猫    }
1176141fdfbS猫头猫    return fileName;
1186141fdfbS猫头猫}
11929fe487bS猫头猫
12029fe487bS猫头猫export function addRandomHash(url: string) {
12129fe487bS猫头猫    if (url.indexOf('#') === -1) {
12229fe487bS猫头猫        return `${url}#${Date.now()}`;
12329fe487bS猫头猫    }
12429fe487bS猫头猫    return url;
12529fe487bS猫头猫}
12629fe487bS猫头猫
12729fe487bS猫头猫export function trimHash(url: string) {
12829fe487bS猫头猫    const index = url.lastIndexOf('#');
12929fe487bS猫头猫    if (index === -1) {
13029fe487bS猫头猫        return url;
13129fe487bS猫头猫    }
13229fe487bS猫头猫    return url.substring(0, index);
13329fe487bS猫头猫}
134f55de8c2S猫头猫
135fd2b24adS猫头猫export function escapeCharacter(str?: string) {
1365589cdf3S猫头猫    return str !== undefined ? `${str}`.replace(/[/|\\?*"<>:]+/g, '_') : '';
137f55de8c2S猫头猫}
138ab55f125S猫头猫
139bae3deccS猫头猫export function getDirectory(dirPath: string) {
140bae3deccS猫头猫    const lastSlash = dirPath.lastIndexOf('/');
141ab55f125S猫头猫    if (lastSlash === -1) {
142bae3deccS猫头猫        return dirPath;
143ab55f125S猫头猫    }
144bae3deccS猫头猫    return dirPath.slice(0, lastSlash);
145ab55f125S猫头猫}
146483fe585S猫头猫
147bae3deccS猫头猫export function getFileName(filePath: string, withoutExt?: boolean) {
148bae3deccS猫头猫    const lastSlash = filePath.lastIndexOf('/');
149a84a85c5S猫头猫    if (lastSlash === -1) {
150bae3deccS猫头猫        return filePath;
151a84a85c5S猫头猫    }
152*e593fd4aS猫头猫    let fileName = filePath.slice(lastSlash + 1);
153a84a85c5S猫头猫    if (withoutExt) {
154a84a85c5S猫头猫        const lastDot = fileName.lastIndexOf('.');
155*e593fd4aS猫头猫        fileName = lastDot === -1 ? fileName : fileName.slice(0, lastDot);
156*e593fd4aS猫头猫    }
157*e593fd4aS猫头猫
158*e593fd4aS猫头猫    try {
159*e593fd4aS猫头猫        return decodeURIComponent(fileName);
160*e593fd4aS猫头猫    } catch {
161a84a85c5S猫头猫        return fileName;
162a84a85c5S猫头猫    }
163a84a85c5S猫头猫}
164a84a85c5S猫头猫
165483fe585S猫头猫export async function mkdirR(directory: string) {
166483fe585S猫头猫    let folder = directory;
1675589cdf3S猫头猫    const checkStack: string[] = [];
168483fe585S猫头猫    while (folder.length > 15) {
169483fe585S猫头猫        checkStack.push(folder);
170483fe585S猫头猫        folder = path.dirname(folder);
171483fe585S猫头猫    }
172483fe585S猫头猫    let existPos = 0;
173483fe585S猫头猫    for (let i = 0; i < checkStack.length; ++i) {
174483fe585S猫头猫        const isExist = await exists(checkStack[i]);
175483fe585S猫头猫        if (isExist) {
176483fe585S猫头猫            existPos = i;
177483fe585S猫头猫            break;
178483fe585S猫头猫        }
179483fe585S猫头猫    }
180483fe585S猫头猫
181483fe585S猫头猫    for (let j = existPos - 1; j >= 0; --j) {
182483fe585S猫头猫        try {
183483fe585S猫头猫            await mkdir(checkStack[j]);
184483fe585S猫头猫        } catch (e) {
185483fe585S猫头猫            console.log('error', e);
186483fe585S猫头猫        }
187483fe585S猫头猫    }
188483fe585S猫头猫}
189740e3947S猫头猫
190740e3947S猫头猫export async function writeInChunks(
191740e3947S猫头猫    filePath: string,
192740e3947S猫头猫    data,
193740e3947S猫头猫    chunkSize = 1024 * 1024 * 2,
194740e3947S猫头猫) {
195740e3947S猫头猫    let offset = 0;
196740e3947S猫头猫    console.log('here');
197740e3947S猫头猫    if (await exists(filePath)) {
198740e3947S猫头猫        await unlink(filePath);
199740e3947S猫头猫    }
200740e3947S猫头猫
201740e3947S猫头猫    while (offset < data.length) {
202740e3947S猫头猫        const chunk = data.slice(offset, offset + chunkSize);
203740e3947S猫头猫        if (offset === 0) {
204740e3947S猫头猫            await RNFS.writeFile(filePath, chunk, 'utf8');
205740e3947S猫头猫        } else {
206740e3947S猫头猫            await RNFS.appendFile(filePath, chunk, 'utf8');
207740e3947S猫头猫        }
208740e3947S猫头猫        offset += chunkSize;
209740e3947S猫头猫    }
210740e3947S猫头猫}
211