import { WriteFileOptions,ReadFileOptions, MkDirOptions,RmDirOptions,UnLinkOptions,ReadDirOptions,AccessOptions,RenameOptions,GetFileInfoOptions,CopyFileOptions,StatOptions } from "../interface.uts" import { ReadFileSuccessResult, FileManagerSuccessResult,ReadDirSuccessResult,AccessSuccessResult,GetFileInfoSuccessResult,StatSuccessResult,FileStats,Stats } from "../interface.uts" import { GetFileSystemManager,FileSystemManager} from "../interface.uts" import { UniErrorSubject, UniErrors } from "../unierror.uts" import File from "java.io.File" import Base64 from "android.util.Base64" import MessageDigest from 'java.security.MessageDigest'; import FileInputStream from 'java.io.FileInputStream'; import Charsets from "kotlin.text.Charsets" class AndroidFileSystemManager implements FileSystemManager{ public stat(options: StatOptions){ let currentDispatcher = UTSAndroid.getDispatcher() UTSAndroid.getDispatcher('io').async(function(_){ currentDispatcher.async(function(_){ let filePath = UTSAndroid.convert2AbsFullPath(options.path) let isSandyBox = isSandyBoxPath(filePath,true) if (!isSandyBox) { currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300013, UniErrors.get(1300013)! + ":" + options.path); options.fail?.(err) options.complete?.(err) }) return } let targetFile = new File(filePath) if (!targetFile.exists()) { /** * 文件不存在 */ currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300002, UniErrors.get(1300002)! + ":" + options.path); options.fail?.(err) options.complete?.(err) }) return } if (options.recursive == true && targetFile.isDirectory()) { // 如果当前是目录,并且设置 则需要遍历所有子目录 let res:Array = [] /** * 与文件不同的是,需要迭代下属的文件 */ targetFile.walk() .onEnter(function(file:File):boolean{ if(file.isDirectory()){ return true } return false }) .iterator() .forEach(function(file:File){ let mode = 0 let filesize = 0; let perStats = wrapStats(file) let perFileStats = new FileStats(file.getPath(),perStats) res.add(perFileStats) }) let success = new StatSuccessResult("stat:ok",res) options.success?.(success) options.complete?.(success) }else{ // 默认是false,只读取当前一个文件 let mode = 0 let filesize = 0; let rootStats = new wrapStats(targetFile) let rootFileStats = new FileStats(targetFile.getPath(),rootStats) let res:Array = [rootFileStats] let success = new StatSuccessResult("stat:ok",res) options.success?.(success) options.complete?.(success) } }) },null) } public getFileInfo(options: GetFileInfoOptions){ let currentDispatcher = UTSAndroid.getDispatcher() UTSAndroid.getDispatcher('io').async(function(_){ let filePath = UTSAndroid.convert2AbsFullPath(options.filePath) let isSandyBox = isSandyBoxPath(filePath,true) if (!isSandyBox) { currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300013, UniErrors.get(1300013)! + ":" + options.filePath); options.fail?.(err) options.complete?.(err) }) return } let targetFile = new File(filePath) if (!targetFile.exists()) { /** * 文件不存在 */ currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300002, UniErrors.get(1300002)! + ":" + options.filePath); options.fail?.(err) options.complete?.(err) }) return } if (targetFile.isDirectory()) { /** * 文件是个目录 */ currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300021, UniErrors.get(1300021)! + ":" + options.filePath); options.fail?.(err) options.complete?.(err) }) return } if(options.digestAlgorithm == null){ options.digestAlgorithm = "md5" } if (options.digestAlgorithm!.toLowerCase() != 'md5' && options.digestAlgorithm!.toLowerCase() != 'sha1') { /** * invalid digestAlgorithm */ currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300022, UniErrors.get(1300022)! + ":invalid digestAlgorithm " + options.digestAlgorithm); options.fail?.(err) options.complete?.(err) }) return } let md5Digest = MessageDigest.getInstance(options.digestAlgorithm!) let fileLen = targetFile.length() // 使用缓冲区读取文件内容 let buffer = new ByteArray(8192) let fis = new FileInputStream(targetFile) let len = 0 while (len != -1) { len = fis.read(buffer) if(len != -1){ md5Digest.update(buffer, 0, len.toInt()) } } fis.close(); let digestByte = md5Digest.digest(); // byte to string let strHexString = new StringBuffer(); // byte buffer for (let i = 0; i < digestByte.size; i++) { // 取0xff部分 let hex = Integer.toHexString(0xff & digestByte[i.toInt()].toInt()); if (hex.length == 1) { strHexString.append('0'); } strHexString.append(hex); } // 得到返回結果 let sign = strHexString.toString(); currentDispatcher.async(function(_){ let success = new GetFileInfoSuccessResult(sign,fileLen,"getFileInfo:ok") options.success?.(success) options.complete?.(success) }) },null) } public copyFileSync(srcPath:string,destPath:string):number{ let filePath = UTSAndroid.convert2AbsFullPath(srcPath) let isSandyBox = isSandyBoxPath(filePath,true) if (!isSandyBox) { return 1300013 } let targetFile = new File(filePath) if (!targetFile.exists()) { /** * 文件不存在 */ return 1300002 } let newFilePath = UTSAndroid.convert2AbsFullPath(destPath) isSandyBox = isSandyBoxPath(newFilePath,false) if (!isSandyBox) { return 1300013 } let newFile = new File(newFilePath) if (newFile.getParentFile() == null || !newFile.getParentFile()!.exists()) { /** * 父文件不存在 */ return 1300002 } let copyRetFile = targetFile.copyTo(newFile,true) if (!copyRetFile.exists()) { // 调用系统api 失败 return 1300201 } return 0 } public copyFile(options: CopyFileOptions){ let currentDispatcher = UTSAndroid.getDispatcher() UTSAndroid.getDispatcher('io').async(function(_){ // 检查来源文件 let filePath = UTSAndroid.convert2AbsFullPath(options.srcPath) if(filePath.startsWith("/android_asset/")){ // 用户访问的是asset 路径,此时不是释放模式 let exceptionInfo:Exception|null = null let byteArray = new ByteArray(0) try { let assetName = filePath.substring("/android_asset/".length) let assetStream = UTSAndroid.getAppContext()!.getResources().getAssets().open(assetName); let byteLen = assetStream.available(); byteArray = new ByteArray(byteLen) assetStream.read(byteArray); } catch (e:Exception) { exceptionInfo = e } if(exceptionInfo != null){ currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300201, UniErrors.get(1300201)! + ":" + exceptionInfo.message); options.fail?.(err) options.complete?.(err) }) return } // 检查目标文件 let newFilePath = UTSAndroid.convert2AbsFullPath(options.destPath) console.log("newFilePath",newFilePath) let isSandyBox = isSandyBoxPath(newFilePath,false) if (!isSandyBox) { currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300013, UniErrors.get(1300013)! + ":" + options.destPath); options.fail?.(err) options.complete?.(err) }) return } let newFile = new File(newFilePath) if (newFile.getParentFile()!=null && !newFile.getParentFile()!.exists()) { /** * 父文件不存在 */ currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300002, UniErrors.get(1300002)! +":" + options.destPath); options.fail?.(err) options.complete?.(err) }) return } newFile.writeBytes(byteArray) if (!newFile.exists()) { // 调用系统api 失败 currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300201, UniErrors.get(1300201)!); options.fail?.(err) options.complete?.(err) }) return } currentDispatcher.async(function(_){ let success = new FileManagerSuccessResult("copyFile:ok") options.success?.(success) options.complete?.(success) }) }else{ let isSandyBox = isSandyBoxPath(filePath,true) if (!isSandyBox) { currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300013, UniErrors.get(1300013)! + ":" + options.srcPath); options.fail?.(err) options.complete?.(err) }) return } let targetFile = new File(filePath) if (!targetFile.exists()) { /** * 文件不存在 */ currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300002, UniErrors.get(1300002)! + ":" + options.srcPath); options.fail?.(err) options.complete?.(err) }) return } // 检查目标文件 let newFilePath = UTSAndroid.convert2AbsFullPath(options.destPath) isSandyBox = isSandyBoxPath(newFilePath,false) if (!isSandyBox) { currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300013, UniErrors.get(1300013)! + ":" + options.destPath); options.fail?.(err) options.complete?.(err) }) return } let newFile = new File(newFilePath) if (newFile.getParentFile()!=null && !newFile.getParentFile()!.exists()) { /** * 父文件不存在 */ currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300002, UniErrors.get(1300002)! +":" + options.destPath); options.fail?.(err) options.complete?.(err) }) return } let copyRetFile = targetFile.copyTo(newFile,true) if (!copyRetFile.exists()) { // 调用系统api 失败 currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300201, UniErrors.get(1300201)!); options.fail?.(err) options.complete?.(err) }) return } currentDispatcher.async(function(_){ let success = new FileManagerSuccessResult("copyFile:ok") options.success?.(success) options.complete?.(success) }) } },null) } public renameSync(oldPath:string,newPath:string):number{ let filePath = UTSAndroid.convert2AbsFullPath(oldPath) let isSandyBox = isSandyBoxPath(filePath,false) if (!isSandyBox) { return 1300013 } let targetFile = new File(filePath) if (!targetFile.exists()) { /** * 文件不存在 */ return 1300002 } let newFilePath = UTSAndroid.convert2AbsFullPath(newPath) isSandyBox = isSandyBoxPath(newFilePath,false) if (!isSandyBox) { return 1300013 } let newFile = new File(newFilePath) if (newFile.getParentFile() == null || !newFile.getParentFile()!.exists()) { /** * 父文件不存在 */ return 1300002 } let renameRet = targetFile.renameTo(newFile) if (!renameRet) { // 调用系统api 失败 return 1300201 } return 0 } public rename(options: RenameOptions){ let currentDispatcher = UTSAndroid.getDispatcher() UTSAndroid.getDispatcher('io').async(function(_){ let filePath = UTSAndroid.convert2AbsFullPath(options.oldPath) let isSandyBox = isSandyBoxPath(filePath,false) if (!isSandyBox) { currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300013, UniErrors.get(1300013)! +":" + options.oldPath); options.fail?.(err) options.complete?.(err) }) return } let targetFile = new File(filePath) if (!targetFile.exists()) { /** * 文件不存在 */ currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300002, UniErrors.get(1300002)! +":" + options.oldPath); options.fail?.(err) options.complete?.(err) }) return } let newFilePath = UTSAndroid.convert2AbsFullPath(options.newPath) isSandyBox = isSandyBoxPath(newFilePath,false) if (!isSandyBox) { currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300013, UniErrors.get(1300013)! +":" + options.newPath); options.fail?.(err) options.complete?.(err) }) return } let newFile = new File(newFilePath) if (newFile.getParentFile() == null || !newFile.getParentFile()!.exists()) { /** * 父文件不存在 */ currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300002, UniErrors.get(1300002)! +":" + options.newPath); options.fail?.(err) options.complete?.(err) }) return } let renameRet = targetFile.renameTo(newFile) if (!renameRet) { // 调用系统api 失败 currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300201, UniErrors.get(1300201)!); options.fail?.(err) options.complete?.(err) }) return } currentDispatcher.async(function(_){ let success = new FileManagerSuccessResult("rename:ok") options.success?.(success) options.complete?.(success) }) },null) } public accessSync(path: string):number{ let filePath = UTSAndroid.convert2AbsFullPath(path) let targetFile = new File(filePath) let isSandyBox = isSandyBoxPath(filePath,true) if (!isSandyBox) { return 1300013 } if (!targetFile.exists()) { /** * 文件不存在,或者不是文件夹,异常 */ return 1300002 } return 0 } public access(options: AccessOptions){ let currentDispatcher = UTSAndroid.getDispatcher() UTSAndroid.getDispatcher('io').async(function(_){ let filePath = UTSAndroid.convert2AbsFullPath(options.path) let targetFile = new File(filePath) let isSandyBox = isSandyBoxPath(filePath,true) if (!isSandyBox) { currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300013, UniErrors.get(1300013)! +":" + options.path); options.fail?.(err) options.complete?.(err) }) return } if (!targetFile.exists()) { /** * 文件不存在,或者不是文件夹,异常 */ currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300002, UniErrors.get(1300002)! +":" + options.path); options.fail?.(err) options.complete?.(err) }) return } currentDispatcher.async(function(_){ // 成功 let success = new FileManagerSuccessResult("access:ok") options.success?.(success) options.complete?.(success) }) },null) } readdirSync(dirPath: string): string[]|null{ let filePath = UTSAndroid.convert2AbsFullPath(dirPath) let isSandyBox = isSandyBoxPath(filePath,true) if (!isSandyBox) { return null } let targetFile = new File(filePath) if (!targetFile.exists() || !targetFile.isDirectory()) { /** * 文件不存在,或者不是文件夹,异常 */ return null } return UTSArray.fromNative(targetFile.list()!) } public readdir(options: ReadDirOptions){ let currentDispatcher = UTSAndroid.getDispatcher() UTSAndroid.getDispatcher('io').async(function(_){ let filePath = UTSAndroid.convert2AbsFullPath(options.dirPath) let isSandyBox = isSandyBoxPath(filePath,true) if (!isSandyBox) { currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300013, UniErrors.get(1300013)! +":" + options.dirPath); options.fail?.(err) options.complete?.(err) }) return } let targetFile = new File(filePath) if (!targetFile.exists() || !targetFile.isDirectory()) { /** * 文件不存在,或者不是文件夹,异常 */ currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300002, UniErrors.get(1300002)! +":" + options.dirPath); options.fail?.(err) options.complete?.(err) }) return } let success = new ReadDirSuccessResult(UTSArray.fromNative(targetFile.list())) currentDispatcher.async(function(_){ options.success?.(success) options.complete?.(success) }) },null) } public rmdirSync(dirPath: string,recursive:boolean): number { /** * 遗留问题,无法知道是否属于沙盒路径 */ let filePath = UTSAndroid.convert2AbsFullPath(dirPath) let targetFile = new File(filePath) let isSandyBox = isSandyBoxPath(filePath,false) if (!isSandyBox) { return 1300013 } if (!targetFile.exists()) { /** * 文件不存在 */ return 1300002 } if(!recursive){ // 没有设置递归,则需要检查是否保存子目录 if(targetFile.list().size > 0){ // 存在子目录 return 1300066 } }else{ // 递归删除文件夹下全部内容,如果全部都是文件夹,则可以递归删除,否则返回错误 let hasFileFlag = false targetFile.walk() .onEnter(function(file:File):boolean{ if(file.isDirectory()){ return true } return false }) .iterator() .forEach(function(file:File){ if(file.isFile()){ hasFileFlag = true } }) if(hasFileFlag){ return 1300066 } let delRet = targetFile.deleteRecursively() if (!delRet) { // 调用系统api 失败 return 1300201 } } return 0 } public mkdirSync(dirPath: string,recursive:boolean): number { /** * 遗留问题,无法知道是否属于沙盒路径 */ let filePath = UTSAndroid.convert2AbsFullPath(dirPath) let targetFile = new File(filePath) let isSandyBox = isSandyBoxPath(filePath,false) if (!isSandyBox) { return 1300013 } if (!targetFile.exists()) { /** * 文件不存在 */ return 1300002 } if(!recursive){ // 没有设置递归,则需要检查是否保存子目录 let childList = targetFile.list() if(childList != null && childList.size > 0){ // 存在子目录 return 1300066 } }else{ // 递归删除文件夹下全部内容,如果全部都是文件夹,则可以递归删除,否则返回错误 let hasFileFlag = false targetFile.walk() .onEnter(function(file:File):boolean{ if(file.isDirectory()){ return true } return false }) .iterator() .forEach(function(file:File){ if(file.isFile()){ hasFileFlag = true } }) if(hasFileFlag){ // 存在不是目录的文件 return 1300066 } let delRet = targetFile.deleteRecursively() if (!delRet) { // 调用系统api 失败 return 1300201 } } return 0 } public rmdir(options : RmDirOptions) { let filePath = UTSAndroid.convert2AbsFullPath(options.dirPath) let targetFile = new File(filePath) let currentDispatcher = UTSAndroid.getDispatcher() UTSAndroid.getDispatcher('io').async(function(_){ let isSandyBox = isSandyBoxPath(filePath,false) if (!isSandyBox) { currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300013, UniErrors.get(1300013)! +":" + options.dirPath); options.fail?.(err) options.complete?.(err) }) return } if (!targetFile.exists() || !targetFile.isDirectory()) { /** * 文件不存在 或者 文件是不是文件夹 */ currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300002, UniErrors.get(1300002)! +":" + options.dirPath); options.fail?.(err) options.complete?.(err) }) return } if(!options.recursive){ // 没有设置递归,则需要检查是否保存子目录 let childList = targetFile.list() if(childList != null && childList.size > 0){ // 存在子目录 currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300066, UniErrors.get(1300066)! +":" + options.dirPath); options.fail?.(err) options.complete?.(err) }) return } }else{ // 递归删除文件夹下全部内容,如果全部都是文件夹,则可以递归删除,否则返回错误 let hasFileFlag = false targetFile.walk() .onEnter(function(file:File):boolean{ if(file.isDirectory()){ return true } return false }) .iterator() .forEach(function(file:File){ if(file.isFile()){ hasFileFlag = true } }) if(hasFileFlag){ // 存在不是目录的文件 currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300066, UniErrors.get(1300066)! +":" + options.dirPath); options.fail?.(err) options.complete?.(err) }) return } let delRet = targetFile.deleteRecursively() if (!delRet) { // 调用系统api 失败 currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300201, UniErrors.get(1300201)! +":" + options.dirPath); options.fail?.(err) options.complete?.(err) }) return } } let success = new FileManagerSuccessResult("rmdir:ok") // 删除成功 currentDispatcher.async(function(_){ options.success?.(success) options.complete?.(success) }) },null) } public mkdir(options : MkDirOptions) { let currentDispatcher = UTSAndroid.getDispatcher() UTSAndroid.getDispatcher('io').async(function(_){ if(options.dirPath.isEmpty()){ currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300066, UniErrors.get(1300066)!); options.fail?.(err) options.complete?.(err) }) return } let filePath = UTSAndroid.convert2AbsFullPath(options.dirPath) let isSandyBox = isSandyBoxPath(filePath,false) if (!isSandyBox) { currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300013, UniErrors.get(1300013)! +":" + options.dirPath); options.fail?.(err) options.complete?.(err) }) return } let targetFile = new File(filePath) if (targetFile.exists()) { /** * 文件已经存在,则无法继续创建 */ currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1301005, UniErrors.get(1301005)! +":" + options.dirPath); options.fail?.(err) options.complete?.(err) }) return } if(!options.recursive){ // 没有设置递归创建 if(targetFile.getParentFile() == null || !targetFile.getParentFile()!.exists()){ currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300002, UniErrors.get(1300002)! +":" + options.dirPath); options.fail?.(err) options.complete?.(err) }) return }else{ // 父文件夹存在,则继续创建 let mkRet = targetFile.mkdir() if (!mkRet) { // 调用系统api 失败 currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300201, UniErrors.get(1300201)! +":" + options.dirPath); options.fail?.(err) options.complete?.(err) }) return } } }else{ // 设置了递归 let mkRet = targetFile.mkdirs() if (!mkRet) { // 调用系统api 失败 currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300201, UniErrors.get(1300201)! +":" + options.dirPath); options.fail?.(err) options.complete?.(err) }) return } } currentDispatcher.async(function(_){ let success = new FileManagerSuccessResult("mkdir:ok") // 删除成功 options.success?.(success) options.complete?.(success) }) },null) } unlinkSync(filePath: string): number { let nextFilePath = UTSAndroid.convert2AbsFullPath(filePath) let isSandyBox = isSandyBoxPath(nextFilePath,false) if (!isSandyBox) { return 1300013 } let targetFile = new File(nextFilePath) if (!targetFile.exists()) { return 1300002 } // 文件存在,则进行删除操作 let delRet = targetFile.delete() if (!delRet) { // 调用系统api 删除失败 return 1300201 } return 0 } public unlink(options : UnLinkOptions) { /** * 遗留问题,无法知道是否属于沙盒路径 */ let filePath = UTSAndroid.convert2AbsFullPath(options.filePath) let currentDispatcher = UTSAndroid.getDispatcher() UTSAndroid.getDispatcher('io').async(function(_){ let isSandyBox = isSandyBoxPath(filePath,false) if (!isSandyBox) { currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300013, UniErrors.get(1300013)! + ":" +options.filePath); options.fail?.(err) options.complete?.(err) }) return } let targetFile = new File(filePath) if (!targetFile.exists()) { currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300002, UniErrors.get(1300002)! +":" + options.filePath); options.fail?.(err) options.complete?.(err) }) return } // 文件存在,则进行删除操作 let delRet = targetFile.delete() if (!delRet) { // 调用系统api 删除失败 currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300201, UniErrors.get(1300201)! +":" + options.filePath); options.fail?.(err) options.complete?.(err) }) return } currentDispatcher.async(function(_){ let success = new FileManagerSuccessResult("unlink:ok") // 删除成功 options.success?.(success) options.complete?.(success) }) },null) } public readFileSync(filePath: string,encoding:string): string|null{ // 判断type 是否合法 if(encoding.toLowerCase() != 'base64' && encoding.toLowerCase() != 'utf-8'){ return null } let nextFilePath = UTSAndroid.convert2AbsFullPath(filePath) let isSandyBox = isSandyBoxPath(nextFilePath,true) if (!isSandyBox) { return null } let targetFile = new File(nextFilePath) if (!targetFile.exists()) { return null } if (targetFile.isDirectory()) { return null } /** * 文件超过100M,会超过应用内存 */ if (targetFile.length() > 100 * 1024 * 1024) { return null } if(encoding == 'base64'){ // base64 let byteArray = targetFile.readBytes() let base64Content = Base64.encodeToString(byteArray,Base64.NO_WRAP) return base64Content }else{ // text let text = targetFile.readText() return text } } public readFile(options : ReadFileOptions) { // 判断type 是否合法 if(options.encoding == null){ options.encoding = "utf-8" } if(options.encoding.toLowerCase() != 'base64' && options.encoding.toLowerCase() != 'utf-8' && options.encoding.toLowerCase() != 'ascii'){ let err = new UniError(UniErrorSubject, 1200002, UniErrors.get(1200002)!); options.fail?.(err) options.complete?.(err) return } let currentDispatcher = UTSAndroid.getDispatcher() /** * 执行真正的加载行为,为了避免阻塞分发到 io任务序列 */ UTSAndroid.getDispatcher('io').async(function(_){ let filePath = UTSAndroid.convert2AbsFullPath(options.filePath) if(filePath.startsWith("/android_asset/")){ // 用户访问的是asset 路径,此时不是释放模式 let exceptionInfo:Exception|null = null let byteArray = new ByteArray(0) try { let assetName = filePath.substring("/android_asset/".length) let assetStream = UTSAndroid.getAppContext()!.getResources().getAssets().open(assetName); let byteLen = assetStream.available(); byteArray = new ByteArray(byteLen) assetStream.read(byteArray); } catch (e:Exception) { exceptionInfo = e } if(exceptionInfo != null){ currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300201, UniErrors.get(1300201)! + ":" + exceptionInfo.message); options.fail?.(err) options.complete?.(err) }) return } let ret : ReadFileSuccessResult = { data : "" } if(options.encoding.toLowerCase() == 'base64'){ // base64 let base64Content = Base64.encodeToString(byteArray,Base64.NO_WRAP) ret.data = base64Content }else if(options.encoding.toLowerCase() == "ascii"){ // ascii let text = new String(byteArray,Charsets.US_ASCII) ret.data = text } else{ // utf-8 兜底 let text = new String(byteArray,Charsets.UTF_8) ret.data = text } currentDispatcher.async(function(_){ options.success?.(ret) options.complete?.(ret) }) }else{ let isSandyBox = isSandyBoxPath(filePath,true) if (!isSandyBox) { currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300013, UniErrors.get(1300013)! +":" + options.filePath); options.fail?.(err) options.complete?.(err) }) return } let targetFile = new File(filePath) if (!targetFile.exists()) { currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject, 1300002, UniErrors.get(1300002)! +":" + options.filePath); options.fail?.(err) options.complete?.(err) }) return } if (targetFile.isDirectory()) { currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject,1301003,UniErrors.get(1301003)!); options.fail?.(err) options.complete?.(err) }) return } /** * 文件超过100M,会超过应用内存 */ if (targetFile.length() > 100 * 1024 * 1024) { currentDispatcher.async(function(_){ let err = new UniError(UniErrorSubject,1300202,UniErrors.get(1300202)!); options.fail?.(err) options.complete?.(err) }) return } let ret : ReadFileSuccessResult = { data : "" } if(options.encoding.toLowerCase() == 'base64'){ // base64 let byteArray = targetFile.readBytes() let base64Content = Base64.encodeToString(byteArray,Base64.NO_WRAP) ret.data = base64Content }else if(options.encoding.toLowerCase() == "ascii"){ // ascii let text = targetFile.readText(Charsets.US_ASCII) ret.data = text } else{ // utf-8 兜底 let text = targetFile.readText(Charsets.UTF_8) ret.data = text } currentDispatcher.async(function(_){ options.success?.(ret) options.complete?.(ret) }) } },null) } public writeFileSync(filePath: string,data:string): number{ // 判断type 是否合法 let nextFilePath = UTSAndroid.convert2AbsFullPath(filePath) let isSandyBox = isSandyBoxPath(nextFilePath,false) if (!isSandyBox) { return 1300013 } let nextFile = new File(nextFilePath) if(nextFile.exists() && nextFile.isDirectory()){ // 出错了,目标文件已存在,并且是个目录 return 1301003 } /** * 如果上一级目录不存在,创建之 */ if(!nextFile.parentFile!.exists()){ nextFile.parentFile!.mkdirs() } if(!nextFile.exists()){ nextFile.createNewFile() } // 写入文本,暂时只支持覆盖写入 nextFile.writeText(data) return 0 } public writeFile(options : WriteFileOptions) { if(options.encoding == null){ options.encoding = "utf-8" } if(options.encoding.toLowerCase() != 'base64' && options.encoding.toLowerCase() != 'utf-8' && options.encoding.toLowerCase() != 'ascii'){ let err = new UniError(UniErrorSubject, 1200002, UniErrors.get(1200002)!); options.fail?.(err) options.complete?.(err) return } // 判断type 是否合法 let filePath = UTSAndroid.convert2AbsFullPath(options.filePath) let isSandyBox = isSandyBoxPath(filePath,false) if (!isSandyBox) { let err = new UniError(UniErrorSubject, 1300013, UniErrors.get(1300013)! +":" + options.filePath); options.fail?.(err) options.complete?.(err) return } let nextFile = new File(filePath) if(nextFile.exists() && nextFile.isDirectory()){ // 出错了,目标文件已存在,并且是个目录 let err = new UniError(UniErrorSubject,1301003,UniErrors.get(1301003)!); options.fail?.(err) options.complete?.(err) return } let currentDispatcher = UTSAndroid.getDispatcher() UTSAndroid.getDispatcher('io').async(function(_){ /** * 如果上一级目录不存在,创建之 */ if(!nextFile.parentFile!.exists()){ nextFile.parentFile!.mkdirs() } if(!nextFile.exists()){ nextFile.createNewFile() } // 写入文本,根据不同的编码内容写入不同的数据 if(options.encoding.toLowerCase() == 'ascii'){ // 与微信保持一致,以UTF-16 BE首字节为ascii let charArray = options.data.toCharArray() let charNum = charArray.size let byteArray = ByteArray(charNum) let index = 0; for(;index < charNum;index++){ let perByte = charArray[index.toInt()].toChar().toByte() byteArray.set(index.toInt(),perByte) } nextFile.writeBytes(byteArray) }else if(options.encoding.toLowerCase() == 'base64'){ // base64 nextFile.writeBytes(Base64.decode(options.data,Base64.NO_WRAP)) }else{ // utf-8 兜底 nextFile.writeText(options.data,Charsets.UTF_8) } let ret = FileManagerSuccessResult("writeFile:ok") currentDispatcher.async(function(_){ options.success?.(ret) options.complete?.(ret) }) },null) } } export const getFileSystemManager:GetFileSystemManager = function ():FileSystemManager { return new AndroidFileSystemManager() }; /** * 判断传入的路径是否是沙盒路径,如果不是则不能继续操作 */ function isSandyBoxPath(inputPath:string,onlyRead:boolean):boolean{ /** * 第一条规则,判断是否操作的是应用资源目录。开发者具备该目录下读取的权限操作 */ let appResRoot = UTSAndroid.convert2AbsFullPath(uni.env.APP_RESOURCE_PATH) if(inputPath.startsWith(appResRoot)){ // 路径是应用资源目录 if(onlyRead){ // 并且是读取操作,返回 return true }else{ // 不是读取 return false } } /** * 第二条规则,是否属于应用根目录 SANDBOX_PATH */ let sandyBoxRoot = UTSAndroid.convert2AbsFullPath(uni.env.SANDBOX_PATH) if(inputPath.startsWith(sandyBoxRoot)){ // 是否是应用根目录 return true } /** * 第三条规则,是否属于应用内置根目录 ANDROID_INTERNAL_SANDBOX_PATH */ let innerSandyBoxRoot = UTSAndroid.convert2AbsFullPath(uni.env.ANDROID_INTERNAL_SANDBOX_PATH) if(inputPath.startsWith(innerSandyBoxRoot)){ // 是否是应用根目录 return true } return false } function wrapStats(sourceFile:File):Stats{ let stats = new Stats() stats.mIsFile = sourceFile.isFile() stats.lastModifiedTime = sourceFile.lastModified() if(sourceFile.isFile()){ stats.size = sourceFile.length() } return stats }