using System; using System.Collections.Generic; using System.IO; using System.Linq; using ET; using UnityEngine; using UnityEngine.Networking; namespace GFGGame { public class PictureDataManager : SingletonBase { //本地地址 private const string _loadUrl = "gfgpicture"; //正在操作的文件队列 private Queue _queueOperateFileList = new Queue(); /// /// 所有照片的二进制 /// private Dictionary _allPicByteDic = new Dictionary(); public async ETTask GetPicNTexture(string tempUrl) { string fileNameKey = GetUrlFileName(tempUrl); if (_allPicByteDic.TryGetValue(fileNameKey, out Texture2D texture2D)) { // 可能存在 if (texture2D != null && texture2D.width > 0 && texture2D.height > 0 && texture2D.GetPixels().Length > 0) { // 检查纹理的格式是否支持 if (texture2D.format == TextureFormat.RGBA32 || texture2D.format == TextureFormat.RGB24) { // 纹理有效,可以正常显示 return texture2D; // 或者转换为 NTexture 对象 } else { Debug.LogError("Texture format is not supported."); // 处理不支持的纹理格式 return await DownloadOrLoadPic(tempUrl); } } else { Debug.LogWarning("Texture is invalid or has no pixels."); // 处理无效的纹理 return await DownloadOrLoadPic(tempUrl); } } //TODO 一定不存在, 需要去进行下载 return await DownloadOrLoadPic(tempUrl); } //从远端进行下载 public async ETTask DownloadOrLoadPic(string tempUrl) { string fileName = GetUrlFileName(tempUrl); Texture2D texture2D = await DownloadPictureAsync(tempUrl); if (texture2D == null) { return GetDefaultTexture(); } //不为null, 以协程的方式存储到内存以及, 本地 _allPicByteDic[fileName] = texture2D; //加入队列 _queueOperateFileList.Enqueue(fileName); SavaPicToLoad().Coroutine(); return texture2D; } //存储图片文件到本地,如果存在就进行删除本地或者覆盖,以当前的为最新的进行记录 public async ETTask SavaPicToLoad() { var tempList = _queueOperateFileList.ToList(); for (int i = 0; i < tempList.Count; i++) { if (_queueOperateFileList.Count == 0) { break; } string fileName = _queueOperateFileList.Dequeue(); if (string.IsNullOrEmpty(fileName)) { continue; } if (!_allPicByteDic.TryGetValue(fileName, out Texture2D texture2D)) { continue; } if (texture2D == null) { continue; } // 获取本地存储路径 string localPath = Path.Combine(Application.persistentDataPath, fileName); // 存储图片文件到本地 try { // 将 Texture2D 转换为字节数组 byte[] imageData = texture2D.EncodeToPNG(); // 如果文件已经存在,则覆盖 if (File.Exists(localPath)) { File.Delete(localPath); } // 将字节数组写入文件 File.WriteAllBytes(localPath, imageData); } catch (Exception ex) { Debug.LogError($"Failed to save image to local path: {ex.Message}"); } } await ETTask.CompletedTask; } private async ETTask DownloadPictureAsync(string tempUrl, int count = 0) { string fileName = GetUrlFileName(tempUrl); if (count >= 3) { PromptController.Instance.ShowFloatTextPrompt("下载失败"); ViewManager.Hide(); return null; } using (UnityWebRequest request = UnityWebRequestTexture.GetTexture(tempUrl)) { var asyncOperation = request.SendWebRequest(); while (!asyncOperation.isDone) { await TimerComponent.Instance.WaitTillAsync(100); // 等待一段时间后继续检查 } if (request.result == UnityWebRequest.Result.ProtocolError || request.result == UnityWebRequest.Result.ConnectionError) { count += 1; return await DownloadPictureAsync(tempUrl, count); // 递归重试 } else { Texture2D texture = (request.downloadHandler as DownloadHandlerTexture).texture; return texture; } } } // 获取存储文件的完整路径 public static string GetFilePath(string fileName) { // 获取持久化数据路径 string persistentDataPath = Application.persistentDataPath; // 创建“zhaoPian”文件夹路径 string folderPath = Path.Combine(persistentDataPath, _loadUrl); // 确保文件夹存在 if (!Directory.Exists(folderPath)) { Directory.CreateDirectory(folderPath); } // 返回文件的完整路径 return Path.Combine(folderPath, fileName); } /// /// 获取下载地址的文件名, 包含后缀 TODO 需要增加容错 /// /// /// public static string GetUrlFileName(string url) { // 创建一个 Uri 对象 Uri uri = new Uri(url); // 获取 URL 的路径部分 string path = uri.AbsolutePath; // 从路径中提取文件名 string fileName = System.IO.Path.GetFileName(path); // // 获取不包含扩展名的文件名 // string fileNameWithoutExtension = System.IO.Path.GetFileNameWithoutExtension(fileName); return fileName; } //TODO 默认纹理, 让客户端来修改这个代码, 定义一个默认的 Texture2D private Texture2D GetDefaultTexture() { // 创建一个简单的默认图片,比如纯色或空白图片 Texture2D defaultTexture = new Texture2D(2, 2); Color[] pixels = defaultTexture.GetPixels(); for (int i = 0; i < pixels.Length; i++) { pixels[i] = Color.gray; // 设置为灰色的默认图片 } defaultTexture.SetPixels(pixels); defaultTexture.Apply(); return defaultTexture; } //初始化的时候根据图片保存时间, 加载最多50条到内存中 public void LoadAllImages() { // 获取文件夹路径 string folderPath = Path.Combine(Application.persistentDataPath, _loadUrl); // 检查文件夹是否存在 if (Directory.Exists(folderPath)) { // 获取所有图片文件路径(假设图片格式为.jpg和.png) string[] imageFiles = Directory.GetFiles(folderPath, "*.*", SearchOption.TopDirectoryOnly); // 过滤出图片文件,并按修改时间排序 var imageFileInfos = imageFiles .Where(filePath => filePath.EndsWith(".jpg") || filePath.EndsWith(".png")) .Select(filePath => new FileInfo(filePath)) .OrderByDescending(fileInfo => fileInfo.LastWriteTime) .ToList(); int loadedCount = 0; const int maxImagesToLoad = 50; foreach (var fileInfo in imageFileInfos) { string filePath = fileInfo.FullName; try { // 读取图片数据 byte[] imageData = File.ReadAllBytes(filePath); // 创建纹理并加载数据 Texture2D texture = new Texture2D(2, 2); // 创建一个2x2的空纹理 if (texture.LoadImage(imageData)) { // 提取文件名作为字典的键 string fileName = Path.GetFileName(filePath); // 将纹理添加到字典 _allPicByteDic[fileName] = texture; Debug.Log($"Loaded {fileName}"); loadedCount++; // 如果已经加载了最大数量的图片,停止加载并删除剩余较旧的图片 if (loadedCount >= maxImagesToLoad) { DeleteOldImages(imageFileInfos, loadedCount); return; } } else { Debug.LogWarning($"Failed to load image from {filePath}"); } } catch { Debug.LogWarning($"Error processing file: {filePath}"); } } } else { Debug.LogWarning($"Folder not found: {folderPath}"); } } // 删除较旧的图片 private void DeleteOldImages(List imageFileInfos, int loadedCount) { // 从已经加载的图片后面开始删除 for (int i = loadedCount; i < imageFileInfos.Count; i++) { string filePath = imageFileInfos[i].FullName; try { File.Delete(filePath); Debug.Log($"Deleted {filePath}"); } catch (Exception ex) { Debug.LogWarning($"Failed to delete {filePath}: {ex.Message}"); } } } } }