using System; using System.Collections.Generic; using System.Runtime.InteropServices; using StarkSDKSpace.UNBridgeLib.LitJson; using UnityEngine; using Object = UnityEngine.Object; namespace StarkSDKSpace { public class StarkFileSystemManagerWebGL : StarkFileSystemManager { #if UNITY_WEBGL && !UNITY_EDITOR [DllImport("__Internal")] private static extern string StarkWriteStringFileSync(string filePath, string data, string encoding); #else private static string StarkWriteStringFileSync(string filePath, string data, string encoding) { return StarkFileSystemManagerDefault.Instance.WriteFileSync(filePath, data, encoding); } #endif #if UNITY_WEBGL && !UNITY_EDITOR [DllImport("__Internal")] private static extern string StarkWriteBinFileSync(string filePath, byte[] data, int dataLength); #else private static string StarkWriteBinFileSync(string filePath, byte[] data, int dataLength) { return StarkFileSystemManagerDefault.Instance.WriteFileSync(filePath, data); } #endif #if UNITY_WEBGL && !UNITY_EDITOR [DllImport("__Internal")] private static extern void StarkWriteBinFile(string filePath, byte[] data, int dataLength, string s, string f); #else private static void StarkWriteBinFile(string filePath, byte[] data, int dataLength, string s, string f) { StarkFileSystemManagerDefault.Instance.WriteFileSync(filePath, data); } #endif #if UNITY_WEBGL && !UNITY_EDITOR [DllImport("__Internal")] private static extern void StarkWriteStringFile(string filePath, string data, string encoding, string s, string f); #else private static void StarkWriteStringFile(string filePath, string data, string encoding, string s, string f) { StarkFileSystemManagerDefault.Instance.WriteFileSync(filePath, data, encoding); } #endif #if UNITY_WEBGL && !UNITY_EDITOR [DllImport("__Internal")] private static extern void StarkReadFile(string filePath, string encoding, string callbackId); #else private static void StarkReadFile(string filePath, string encoding, string callbackId) { } #endif #if UNITY_WEBGL && !UNITY_EDITOR [DllImport("__Internal")] private static extern string StarkReadStringFileSync(string filePath, string encoding); #else private static string StarkReadStringFileSync(string filePath, string encoding) { return StarkFileSystemManagerDefault.Instance.ReadFileSync(filePath, encoding); } #endif #if UNITY_WEBGL && !UNITY_EDITOR [DllImport("__Internal")] private static extern int StarkReadBinFileSync(string filePath); #else private static int StarkReadBinFileSync(string filePath) { return 0; } #endif #if UNITY_WEBGL && !UNITY_EDITOR [DllImport("__Internal")] private static extern void StarkShareFileBuffer(byte[] data, string callbackId); #else private static void StarkShareFileBuffer(byte[] data, string callbackId) { } #endif #if UNITY_WEBGL && !UNITY_EDITOR [DllImport("__Internal")] private static extern bool StarkAccessFileSync(string filePath); #else private static bool StarkAccessFileSync(string filePath) { return StarkFileSystemManagerDefault.Instance.AccessSync(filePath); } #endif #if UNITY_WEBGL && !UNITY_EDITOR [DllImport("__Internal")] private static extern void StarkAccessFile(string filePath, string s, string f); #else private static void StarkAccessFile(string filePath, string s, string f) { } #endif #if UNITY_WEBGL && !UNITY_EDITOR [DllImport("__Internal")] private static extern string StarkCopyFileSync(string srcPath, string destPath); #else private static string StarkCopyFileSync(string srcPath, string destPath) { return StarkFileSystemManagerDefault.Instance.CopyFileSync(srcPath, destPath); } #endif #if UNITY_WEBGL && !UNITY_EDITOR [DllImport("__Internal")] private static extern string StarkRenameFileSync(string srcPath, string destPath); #else private static string StarkRenameFileSync(string srcPath, string destPath) { return StarkFileSystemManagerDefault.Instance.RenameFileSync(srcPath, destPath); } #endif #if UNITY_WEBGL && !UNITY_EDITOR [DllImport("__Internal")] private static extern void StarkCopyFile(string srcPath, string destPath, string s, string f); #else private static void StarkCopyFile(string srcPath, string destPath, string s, string f) { StarkFileSystemManagerDefault.Instance.CopyFileSync(srcPath, destPath); } #endif #if UNITY_WEBGL && !UNITY_EDITOR [DllImport("__Internal")] private static extern void StarkRenameFile(string srcPath, string destPath, string s, string f); #else private static void StarkRenameFile(string srcPath, string destPath, string s, string f) { StarkFileSystemManagerDefault.Instance.RenameFileSync(srcPath, destPath); } #endif #if UNITY_WEBGL && !UNITY_EDITOR [DllImport("__Internal")] private static extern string StarkUnlinkSync(string filePath); #else private static string StarkUnlinkSync(string filePath) { return StarkFileSystemManagerDefault.Instance.UnlinkSync(filePath); } #endif #if UNITY_WEBGL && !UNITY_EDITOR [DllImport("__Internal")] private static extern void StarkUnlink(string filePath, string s, string f); #else private static void StarkUnlink(string filePath, string s, string f) { StarkFileSystemManagerDefault.Instance.UnlinkSync(filePath); } #endif #if UNITY_WEBGL && !UNITY_EDITOR [DllImport("__Internal")] private static extern void StarkMkdir(string dirPath, bool recursive, string s, string f); #else private static void StarkMkdir(string dirPath, bool recursive, string s, string f) { StarkFileSystemManagerDefault.Instance.MkdirSync(dirPath); } #endif #if UNITY_WEBGL && !UNITY_EDITOR [DllImport("__Internal")] private static extern string StarkMkdirSync(string dirPath, bool recursive); #else private static string StarkMkdirSync(string dirPath, bool recursive) { return StarkFileSystemManagerDefault.Instance.MkdirSync(dirPath); } #endif #if UNITY_WEBGL && !UNITY_EDITOR [DllImport("__Internal")] private static extern void StarkRmdir(string dirPath, bool recursive, string s, string f); #else private static void StarkRmdir(string dirPath, bool recursive, string s, string f) { StarkFileSystemManagerDefault.Instance.RmdirSync(dirPath); } #endif #if UNITY_WEBGL && !UNITY_EDITOR [DllImport("__Internal")] private static extern string StarkRmdirSync(string dirPath, bool recursive); #else private static string StarkRmdirSync(string dirPath, bool recursive) { return StarkFileSystemManagerDefault.Instance.RmdirSync(dirPath); } #endif #if UNITY_WEBGL && !UNITY_EDITOR [DllImport("__Internal")] private static extern string StarkStatSync(string path); #else private static string StarkStatSync(string path) { return ""; } #endif #if UNITY_WEBGL && !UNITY_EDITOR [DllImport("__Internal")] private static extern void StarkStat(string path, string callbackId); #else private static void StarkStat(string path, string callbackId) { } #endif #if UNITY_WEBGL && !UNITY_EDITOR [DllImport("__Internal")] private static extern void StarkGetSavedFileList(string callbackId); #else private static void StarkGetSavedFileList(string callbackId) { } #endif #if UNITY_WEBGL && !UNITY_EDITOR [DllImport("__Internal")] private static extern string StarkGetCachedPathForUrl(string url); #else private static string StarkGetCachedPathForUrl(string url) { return ""; } #endif public static readonly StarkFileSystemManagerWebGL Instance = new StarkFileSystemManagerWebGL(); private static Dictionary s_readFileParams = new Dictionary(); private static Dictionary s_statParams = new Dictionary(); private static Dictionary s_getSavedFileListParams = new Dictionary(); private static bool _initialized; public StarkFileSystemManagerWebGL() { MigratingData(); CreateStarkFileSystemHandler(); } private void CreateStarkFileSystemHandler() { if (!_initialized) { _initialized = true; GameObject obj = new GameObject(); Object.DontDestroyOnLoad(obj); obj.name = "StarkFileSystemManager"; obj.AddComponent(); } } public class StarkFileSystemHandler : MonoBehaviour { public void HandleNativeCallback(string msg) { Debug.Log($"HandleNativeCallback - {msg}"); StarkCallbackHandler.InvokeResponseCallback(msg); } public void HandleReadFileCallback(string msg) { Debug.Log($"HandleReadFileCallback - {msg}"); var res = JsonUtility.FromJson(msg); var conf = s_readFileParams[res.callbackId]; if (conf == null) { Debug.LogWarning($"HandleReadFileCallback - no callback for callbackId: {res.callbackId}"); return; } s_readFileParams.Remove(res.callbackId); if (res.errCode == 0) { if (string.IsNullOrEmpty(conf.encoding) || conf.encoding.Equals("binary")) { var sharedBuffer = new byte[res.byteLength]; StarkShareFileBuffer(sharedBuffer, res.callbackId); var obj = new StarkReadFileResponse() { binData = sharedBuffer, }; conf.success?.Invoke(obj); } else { var obj = new StarkReadFileResponse() { stringData = res.data }; conf.success?.Invoke(obj); } } else { var obj = new StarkReadFileResponse() { errCode = res.errCode, errMsg = res.errMsg }; conf.fail?.Invoke(obj); } } public void HandleStatCallback(string msg) { Debug.Log($"HandleStatCallback - {msg}"); StarkStatResponse res; try { res = JsonMapper.ToObject(msg); } catch (Exception exception) { Debug.LogError($"failed to parse json data: {msg}, {exception}"); return; } if (res == null) { Debug.LogError("empty response"); return; } var conf = s_statParams[res.callbackId]; if (conf == null) { Debug.LogWarning($"HandleStatCallback - no callback for callbackId: {res.callbackId}"); return; } s_statParams.Remove(res.callbackId); if (res.errCode == 0) { if (res.stat == null) { Debug.LogWarning("empty stat info"); res.stat = new StarkStatInfo(); } conf.success?.Invoke(res); } else { res.stat = new StarkStatInfo(); conf.fail?.Invoke(res); } } public void HandleGetSavedFileListCallback(string msg) { Debug.Log($"HandleGetSavedFileListCallback - {msg}"); StarkGetSavedFileListResponse res; try { res = JsonMapper.ToObject(msg); } catch (Exception exception) { Debug.LogError($"failed to parse json data: {msg}, {exception}"); return; } if (res == null) { Debug.LogError("empty response"); return; } var conf = s_getSavedFileListParams[res.callbackId]; if (conf == null) { Debug.LogWarning($"HandleStatCallback - no callback for callbackId: {res.callbackId}"); return; } s_statParams.Remove(res.callbackId); if (res.errCode == 0) { if (res.fileList == null) { res.fileList = new StarkFileInfo[0]; } conf.success?.Invoke(res); } else { res.fileList = new StarkFileInfo[0]; conf.fail?.Invoke(res); } } } private string FixFilePath(string filePath) { if (filePath.StartsWith(USER_DATA_PATH)) { return filePath; } if (filePath.StartsWith(Application.persistentDataPath)) { filePath = filePath.Replace(Application.persistentDataPath, USER_DATA_PATH); } else { if (filePath.StartsWith("/")) { filePath = filePath.Substring(1); } filePath = $"{USER_DATA_PATH}/{filePath}"; } return filePath; } /// /// 将字符串写入文件(同步) /// /// 要写入的文件路径 /// 要写入的文本 /// 指定写入文件的字符编码 /// 成功返回空字符串,失败返回错误信息 public override string WriteFileSync(string filePath, string data, string encoding = "utf8") { if (string.IsNullOrEmpty(encoding)) { encoding = "utf8"; } return StarkWriteStringFileSync(FixFilePath(filePath), data, encoding); } /// /// 将二进制写入文件(同步) /// /// 要写入的文件路径 /// 要写入的二进制数据 /// 成功返回空字符串,失败返回错误信息 public override string WriteFileSync(string filePath, byte[] data) { return StarkWriteBinFileSync(FixFilePath(filePath), data, data.Length); } /// /// 将二进制写入文件(异步) /// /// public override void WriteFile(WriteFileParam param) { StarkWriteBinFile( FixFilePath(param.filePath), param.data, param.data.Length, StarkCallbackHandler.Add(param.success), StarkCallbackHandler.Add(param.fail) ); } /// /// 将字符串写入文件(异步) /// /// public override void WriteFile(WriteFileStringParam param) { if (string.IsNullOrEmpty(param.encoding)) { param.encoding = "utf8"; } StarkWriteStringFile( FixFilePath(param.filePath), param.data, param.encoding, StarkCallbackHandler.Add(param.success), StarkCallbackHandler.Add(param.fail) ); } /// /// 读取本地文件内容(异步) /// /// public override void ReadFile(ReadFileParam param) { var key = StarkCallbackHandler.MakeKey(); s_readFileParams.Add(key, param); StarkReadFile(FixFilePath(param.filePath), param.encoding, key); } /// /// 从本地文件读取二进制数据数据(同步) /// /// /// 字节数据,读取失败返回null public override byte[] ReadFileSync(string filePath) { if (Application.platform == RuntimePlatform.WebGLPlayer) { filePath = FixFilePath(filePath); var length = StarkReadBinFileSync(filePath); if (length == 0) { return null; } var sharedBuffer = new byte[length]; StarkShareFileBuffer(sharedBuffer, filePath); return sharedBuffer; } else { return System.IO.File.ReadAllBytes(filePath); } } /// /// 从本地文件读取字符串数据(同步) /// /// 要读取的文件的路径 /// 指定读取文件的字符编码, 不能为空 /// 字符串数据,读取失败返回null public override string ReadFileSync(string filePath, string encoding) { return StarkReadStringFileSync(FixFilePath(filePath), encoding); } /// /// 判断文件/目录是否存在(同步) /// /// 要判断是否存在的文件/目录路径 /// 成功返回 true, 失败返回 false public override bool AccessSync(string path) { return StarkAccessFileSync(FixFilePath(path)); } /// /// 判断文件/目录是否存在(异步) /// /// public override void Access(AccessParam param) { StarkAccessFile(FixFilePath(param.path), StarkCallbackHandler.Add(param.success), StarkCallbackHandler.Add(param.fail)); } /// /// 复制文件(同步) /// /// 源文件路径 /// 目标文件路径 /// 成功返回空字符串,失败返回错误信息 public override string CopyFileSync(string srcPath, string destPath) { return StarkCopyFileSync(FixFilePath(srcPath), FixFilePath(destPath)); } /// /// 复制文件(异步) /// /// public override void CopyFile(CopyFileParam param) { StarkCopyFile(FixFilePath(param.srcPath), FixFilePath(param.destPath), StarkCallbackHandler.Add(param.success), StarkCallbackHandler.Add(param.fail)); } /// /// 重命名文件(异步) /// /// public override void RenameFile(RenameFileParam param) { StarkRenameFile(FixFilePath(param.srcPath), FixFilePath(param.destPath), StarkCallbackHandler.Add(param.success), StarkCallbackHandler.Add(param.fail)); } /// /// 重命名文件(同步) /// /// 源文件路径 /// 目标文件路径 /// 成功返回空字符串,失败返回错误信息 public override string RenameFileSync(string srcPath, string destPath) { return StarkRenameFileSync(FixFilePath(srcPath), FixFilePath(destPath)); } /// /// 删除文件(同步) /// /// 源文件路径,支持本地路径 /// 成功返回空字符串,失败返回错误信息 public override string UnlinkSync(string filePath) { return StarkUnlinkSync(FixFilePath(filePath)); } /// /// 删除文件(异步) /// /// public override void Unlink(UnlinkParam param) { StarkUnlink(FixFilePath(param.filePath), StarkCallbackHandler.Add(param.success), StarkCallbackHandler.Add(param.fail)); } /// /// 创建目录(异步) /// /// public override void Mkdir(MkdirParam param) { StarkMkdir(FixFilePath(param.dirPath), param.recursive, StarkCallbackHandler.Add(param.success), StarkCallbackHandler.Add(param.fail)); } /// /// 创建目录(同步) /// /// 创建的目录路径 /// 是否在递归创建该目录的上级目录后再创建该目录。如果对应的上级目录已经存在,则不创建该上级目录。如 dirPath 为 a/b/c/d 且 recursive 为 true,将创建 a 目录,再在 a 目录下创建 b 目录,以此类推直至创建 a/b/c 目录下的 d 目录。 /// 成功返回空字符串,失败返回错误信息 public override string MkdirSync(string dirPath, bool recursive = false) { return StarkMkdirSync(FixFilePath(dirPath), recursive); } /// /// 删除目录(异步) /// /// public override void Rmdir(RmdirParam param) { StarkRmdir(FixFilePath(param.dirPath), param.recursive, StarkCallbackHandler.Add(param.success), StarkCallbackHandler.Add(param.fail)); } /// /// 删除目录(同步) /// /// 创建的目录路径 /// 是否递归删除目录。如果为 true,则删除该目录和该目录下的所有子目录以及文件 。 /// 成功返回空字符串,失败返回错误信息 public override string RmdirSync(string dirPath, bool recursive = false) { return StarkRmdirSync(FixFilePath(dirPath), recursive); } /// /// 读取文件描述信息(同步) /// /// 文件/目录路径 /// 是否递归获取目录下的每个文件的 Stat 信息 /// 是否抛出错误信息,如果抛出错误信息,当文件不存在时则会抛出异常,错误信息从异常中获取。 /// 返回文件信息,如果访问失败则返回null public override StarkStatInfo StatSync(string path, bool throwException = false) { var info = StarkStatSync(FixFilePath(path)); try { return JsonUtility.FromJson(info); } catch (Exception exception) { if (throwException) { if (string.IsNullOrEmpty(info)) { info = "stat failed"; } throw new Exception(info); } return null; } } /// /// 读取文件描述信息(异步) /// /// public override void Stat(StatParam param) { var key = StarkCallbackHandler.MakeKey(); s_statParams.Add(key, param); StarkStat(FixFilePath(param.path), key); } /// /// 获取保存的用户目录文件列表 /// /// public override void GetSavedFileList(GetSavedFileListParam param) { var key = StarkCallbackHandler.MakeKey(); s_getSavedFileListParams.Add(key, param); StarkGetSavedFileList(key); } /// /// 根据url链接获取本地缓存文件路径 /// /// 输入文件下载链接url /// 返回本地缓存文件路径,以scfile://user开头的路径,可以直接用这个路径访问该文件 public override string GetLocalCachedPathForUrl(string url) { return StarkGetCachedPathForUrl(url); } /// /// 判断该url是否有本地缓存文件 /// /// 输入文件下载链接url /// 如果存在缓存文件则返回true,不存在缓存文件则返回false public override bool IsUrlCached(string url) { var path = GetLocalCachedPathForUrl(url); return !string.IsNullOrEmpty(path) && AccessSync(path); } } }