1import pathConst from '@/constants/pathConst'; 2import FastImage from 'react-native-fast-image'; 3import RNFS, { 4 copyFile, 5 downloadFile, 6 exists, 7 mkdir, 8 PicturesDirectoryPath, 9 readDir, 10 unlink, 11 writeFile, 12} from 'react-native-fs'; 13import {errorLog} from './log'; 14import path from 'path-browserify'; 15 16export const galleryBasePath = `${PicturesDirectoryPath}/MusicFree/`; 17 18export async function saveToGallery(src: string) { 19 const fileName = `${galleryBasePath}${Date.now()}.png`; 20 if (!(await exists(galleryBasePath))) { 21 await mkdir(galleryBasePath); 22 } 23 if (await exists(src)) { 24 try { 25 await copyFile(src, fileName); 26 } catch (e) { 27 console.log('... ', e); 28 } 29 } 30 if (src.startsWith('http')) { 31 await downloadFile({ 32 fromUrl: src, 33 toFile: fileName, 34 background: true, 35 }); 36 } 37 if (src.startsWith('data')) { 38 await writeFile(fileName, src); 39 } 40} 41 42export function sizeFormatter(bytes: number | string) { 43 if (typeof bytes === 'string') { 44 return bytes; 45 } 46 if (bytes === 0) { 47 return '0B'; 48 } 49 let k = 1024, 50 sizes = ['B', 'KB', 'MB', 'GB'], 51 i = Math.floor(Math.log(bytes) / Math.log(k)); 52 return (bytes / Math.pow(k, i)).toFixed(1) + sizes[i]; 53} 54 55export async function checkAndCreateDir(dirPath: string) { 56 const filePath = dirPath; 57 try { 58 if (!(await exists(filePath))) { 59 await mkdir(filePath); 60 } 61 } catch (e) { 62 errorLog('无法初始化目录', {path: dirPath, e}); 63 } 64} 65 66async function getFolderSize(dirPath: string): Promise<number> { 67 let size = 0; 68 try { 69 const fns = await readDir(dirPath); 70 for (let fn of fns) { 71 if (fn.isFile()) { 72 size += fn.size; 73 } 74 // todo: 可以改成并行 promise.all 75 if (fn.isDirectory()) { 76 size += await getFolderSize(fn.path); 77 } 78 } 79 } catch {} 80 return size; 81} 82 83export async function getCacheSize( 84 type: 'music' | 'lyric' | 'image', 85): Promise<number> { 86 if (type === 'music') { 87 return getFolderSize(pathConst.musicCachePath); 88 } else if (type === 'lyric') { 89 return getFolderSize(pathConst.lrcCachePath); 90 } else if (type === 'image') { 91 return getFolderSize(pathConst.imageCachePath); 92 } 93 throw new Error(); 94} 95 96export async function clearCache(type: 'music' | 'lyric' | 'image') { 97 if (type === 'music') { 98 try { 99 if (await exists(pathConst.musicCachePath)) { 100 return unlink(pathConst.musicCachePath); 101 } 102 } catch {} 103 } else if (type === 'lyric') { 104 try { 105 const lrcs = readDir(pathConst.lrcCachePath); 106 return Promise.all((await lrcs).map(_ => unlink(_.path))); 107 } catch {} 108 } else if (type === 'image') { 109 return FastImage.clearDiskCache(); 110 } 111} 112 113export function addFileScheme(fileName: string) { 114 if (fileName.startsWith('/')) { 115 return `file://${fileName}`; 116 } 117 return fileName; 118} 119 120export function addRandomHash(url: string) { 121 if (url.indexOf('#') === -1) { 122 return `${url}#${Date.now()}`; 123 } 124 return url; 125} 126 127export function trimHash(url: string) { 128 const index = url.lastIndexOf('#'); 129 if (index === -1) { 130 return url; 131 } 132 return url.substring(0, index); 133} 134 135export function escapeCharacter(str?: string) { 136 return str !== undefined ? `${str}`.replace(/[/|\\?*"<>:]+/g, '_') : ''; 137} 138 139export function getDirectory(dirPath: string) { 140 const lastSlash = dirPath.lastIndexOf('/'); 141 if (lastSlash === -1) { 142 return dirPath; 143 } 144 return dirPath.slice(0, lastSlash); 145} 146 147export function getFileName(filePath: string, withoutExt?: boolean) { 148 const lastSlash = filePath.lastIndexOf('/'); 149 if (lastSlash === -1) { 150 return filePath; 151 } 152 const fileName = filePath.slice(lastSlash + 1); 153 if (withoutExt) { 154 const lastDot = fileName.lastIndexOf('.'); 155 return lastDot === -1 ? fileName : fileName.slice(0, lastDot); 156 } else { 157 return fileName; 158 } 159} 160 161export async function mkdirR(directory: string) { 162 let folder = directory; 163 const checkStack: string[] = []; 164 while (folder.length > 15) { 165 checkStack.push(folder); 166 folder = path.dirname(folder); 167 } 168 let existPos = 0; 169 for (let i = 0; i < checkStack.length; ++i) { 170 const isExist = await exists(checkStack[i]); 171 if (isExist) { 172 existPos = i; 173 break; 174 } 175 } 176 177 for (let j = existPos - 1; j >= 0; --j) { 178 try { 179 await mkdir(checkStack[j]); 180 } catch (e) { 181 console.log('error', e); 182 } 183 } 184} 185 186export async function writeInChunks( 187 filePath: string, 188 data, 189 chunkSize = 1024 * 1024 * 2, 190) { 191 let offset = 0; 192 console.log('here'); 193 if (await exists(filePath)) { 194 await unlink(filePath); 195 } 196 197 while (offset < data.length) { 198 const chunk = data.slice(offset, offset + chunkSize); 199 if (offset === 0) { 200 await RNFS.writeFile(filePath, chunk, 'utf8'); 201 } else { 202 await RNFS.appendFile(filePath, chunk, 'utf8'); 203 } 204 offset += chunkSize; 205 } 206} 207