123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758 |
- using System;
- using System.IO;
- using UnityEngine;
- using System.Text;
- using System.Collections;
- using UnityEngine.Networking;
- using System.Threading.Tasks;
- using System.Threading;
- using System.Collections.Generic;
- namespace XRTool.Util
- {
- /// <summary>
- /// 文件工具类
- /// 下载,写入文件,断点续传,边下边存
- /// 遍历,拷贝文件
- /// 获取文件的MD5等
- /// </summary>
- public class DataFileUtil
- {
- /// <summary>
- /// 预估的写入文件的速度,与真实速度无关,仅仅是模拟评估,预计写入用时
- /// </summary>
- public const float WriteSpeed = 1024 * 1024 * 150f;
- ///// <summary>
- ///// 写入缓存的大小,如果越小,可能会引起卡顿(频繁访问数据)
- ///// </summary>
- //public const int CacheSave = 1024 * 1024 * 2;
- /// <summary>
- /// 图片格式
- /// </summary>
- public static string[] TexturesType = new string[] { "BMP", "EXR", "GIF", "HDR", "IFF", "JPG", "PICT", "PNG", "PSD", "TGA", "TIFF" };
- /// <summary>
- /// 视频格式
- /// </summary>
- public static string[] MoviesType = new string[] { "MOV", "MPG", "MP4", "AVI", "ASF" };
- /// <summary>
- /// 音频格式
- /// </summary>
- public static string[] AudiosType = new string[] { "ACC", "AIFF", "IT", "MOD", "MPEG", "OGGVORBIS", "S3M",
- "AIF", "WAV", "MP3", "OGG","XM","XMA","VAG","AUDIOQUEUE" };
- public static int maxTryCount = 5;
- public const string Extension = ".downing";
- ///// <summary>
- ///// 断点下载,异步读写
- ///// </summary>
- ///// <param name="url"></param>
- ///// <param name="path"></param>
- ///// <param name="completeData"></param>
- ///// <param name="hander"></param>
- ///// <param name="downLoadProcess"></param>
- ///// <returns></returns>
- //public static IEnumerator DownLoadDataAsync(string url, string path,
- // Action<string, UnityWebRequest> completeData, DownloadHandler hander = null, Action<float, float> downLoadProcess = null)
- //{
- // yield return 0;
- //}
- /// <summary>
- /// 下载数据到本地,并将下载的数据返回给到上层应用
- /// 此下载仅应用于可缓存的资源,图片文本等下载,大文件的下载请使用断点下载
- /// </summary>
- /// <param name="url"></param>
- /// <param name="path"></param>
- /// <param name="downLoadProcess"></param>
- /// <param name="completeData"></param>
- /// <param name="isAsync"></param>
- /// <returns></returns>
- public static IEnumerator DownLoadData(string url, string path,
- Action<string, UnityWebRequest> completeData, DownloadHandler hander = null, Action<float, float> downLoadProcess = null, bool isAsync = false)
- {
- UnityWebRequest web = null;
- //DownloadHandlerTexture
- yield return RequestDownData(url, (string error, UnityWebRequest req) =>
- {
- ///下载成功后开始拷贝数据到本地
- if (string.IsNullOrEmpty(error))
- {
- ///同步存储方法
- if (!isAsync)
- {
- SaveDataToFile(path, req.downloadHandler.data);
- downLoadProcess?.Invoke(req.downloadHandler.data.Length, 1);
- completeData?.Invoke(path, req);
- return;
- }
- else
- {
- web = req;
- ///此时,已下载到内存中,但是仍未缓存至内存中,内存数据可用
- completeData?.Invoke(null, req);
- }
- }
- else
- {
- ///下载出错
- completeData?.Invoke(null, null);
- //UnityLog.LogError(error);
- }
- }, hander, (float allLeng, float process) =>
- {
- ///下载的进度,1/1.2,给存储留进度条显示,约等于0.89
- downLoadProcess?.Invoke(allLeng, process / 1.12f);
- });
- ///等待下载完成,此下载是下载到内存中
- if (isAsync && web != null)
- {
- //completeData?.Invoke(true, data);
- yield return SaveDataToFile(path, web.downloadHandler.data, (float saveProcess) =>
- {
- ///更新存储文件的进度
- downLoadProcess?.Invoke(web.downloadHandler.data.Length, saveProcess * 0.1f + 0.9f);
- }, (bool isSuccess, string filePath) =>
- {
- completeData?.Invoke(filePath, web);
- });
- }
- web.Dispose();
- }
- /// <summary>
- /// 请求后台数据接口
- /// </summary>
- /// <returns></returns>
- public static IEnumerator RequestData(string url, Action<string> reqComplete, bool isPost = true,
- Dictionary<string, string> header = null, Dictionary<string, string> form = null, Action complete = null)
- {
- ///表单
- using (UnityWebRequest web = isPost ? UnityWebRequest.Post(url, form) : UnityWebRequest.Get(url))
- {
- if (header != null)
- {
- foreach (var item in header)
- {
- web.SetRequestHeader(item.Key, item.Value);
- }
- }
- yield return web.SendWebRequest();
- if (web.isNetworkError || web.isHttpError)
- {
- UnityLog.LogError("RequestData:" + url + web.error);
- reqComplete?.Invoke(null);
- complete?.Invoke();
- yield break;
- }
- else
- {
- reqComplete?.Invoke(web.downloadHandler.text);
- complete?.Invoke();
- }
- }
- }
- /// <summary>
- /// 获取资源的大小
- /// </summary>
- /// <param name="url"></param>
- /// <param name="getLen"></param>
- /// <returns></returns>
- public static IEnumerator GetDataSize(string url, Action<long> getLen)
- {
- var headRequest = UnityWebRequest.Head(url);
- yield return headRequest.SendWebRequest();
- getLen?.Invoke(long.Parse(headRequest.GetResponseHeader("Content-Length")));
- headRequest.Dispose();
- }
-
-
- /// <summary>
- /// 断点续传
- /// 下载大文件请使用此函数
- /// 注意,请自行检查是否已下载过此文件,此函数不再检查,直接执行下载
- /// </summary>
- /// <param name="url"></param>
- /// <param name="path"></param>
- /// <param name="completeData"></param>
- /// <param name="hander"></param>
- /// <param name="downLoadProcess"></param>
- /// <returns></returns>
- public static IEnumerator DownLoadDataAsync(string url, string path,
- Action<string, UnityWebRequest> completeData, DownloadHandler hander = null, Action<float, float> downLoadProcess = null)
- {
- ///获取文件的大小
- FileStream fs = null;
- long curLen = 0;
- string tmpPath = path + Extension;
- ///文件读写异常,返回错误
- try
- {
- string dir = Path.GetDirectoryName(tmpPath);
- if (!Directory.Exists(dir))
- {
- Directory.CreateDirectory(dir);
- }
- fs = new FileStream(tmpPath, FileMode.OpenOrCreate);
- curLen = fs.Length;
- UnityLog.Log("当前文件大小" + curLen, 2);
- }
- catch (Exception ex)
- {
- if (fs != null)
- {
- fs.Dispose();
- }
- fs = null;
- UnityLog.LogError(tmpPath + ex.ToString());
- downLoadProcess.Invoke(curLen, 0);
- completeData?.Invoke(null, null);
- yield break;
- }
- ///请求获取文件的大小
- ///已下载完成,无需再次下载
- long totalLength = 0;
- yield return GetDataSize(url, (size) =>
- {
- totalLength = size;
- });
- ///当前文件的大小和云端文件大小一致
- ///理论上不会出现这个问题
- if (curLen == totalLength)
- {
- fs.Dispose();
- fs.Close();
- downLoadProcess.Invoke(totalLength, 1);
- ReNameFile(tmpPath,path);
- completeData?.Invoke(path, null);
- yield break;
- }
- ///文件异常,删除文件,重新下载
- ///理论上不会出现这个问题
- else if (curLen > totalLength)
- {
- UnityLog.LogError("文件大小异常" + curLen + "__" + totalLength);
- fs.Dispose();
- fs.Close();
- File.Delete(tmpPath);
- fs = new FileStream(tmpPath, FileMode.OpenOrCreate, FileAccess.Write);
- curLen = fs.Length;
- }
- fs.Seek(curLen, SeekOrigin.Begin);
- bool isSuccess = true;
- yield return RequestDownData(url, (byte[] data, int len) =>
- {
- if (isSuccess && data.Length > 0)
- {
- try
- {
- fs.Write(data, 0, len);
- fs.Flush();
- curLen += len;
- downLoadProcess?.Invoke(curLen, curLen * 1f / totalLength);
- }
- catch (Exception ex)
- {
- UnityLog.LogError(ex.ToString());
- isSuccess = false;
- return;
- }
- }
- else
- {
- ///理论上不会出现这个问题,除非出现异常情况如内存不足等
- //complete?.Invoke(isSuccess, path);
- UnityLog.LogError("Down Error:" + url);
- }
- }, totalLength, curLen, (web) =>
- {
- fs.Dispose();
- fs.Close();
- downLoadProcess.Invoke(totalLength, 1);
- ReNameFile(tmpPath,path);
- completeData?.Invoke(path, web);
- });
- }
- /// <summary>
- /// Get请求下载数据,断点下载,边下载边返回数据进行存储
- /// </summary>
- /// <param name="url">url</param>
- /// <param name="downData">返回获取的数据</param>
- /// <param name="allLen">文件的总大小</param>
- /// <param name="downedLength">已下载的数据</param>
- /// <returns></returns>
- public static IEnumerator RequestDownData(string url, Action<byte[], int> downData, long allLen, long downedLength = 0,
- Action<UnityWebRequest> complete = null)
- {
- //float downTime = Time.time;
- using (UnityWebRequest web = UnityWebRequest.Get(url))
- {
- web.disposeDownloadHandlerOnDispose = true;
- DataDownLoadHandler ddh = new DataDownLoadHandler();
- web.downloadHandler = ddh;
- ddh.OnReceiveData += downData;
- ///请求指定的长度
- web.SetRequestHeader("Range", "bytes=" + downedLength + "-" + allLen);
- yield return web.SendWebRequest();
- if (web.isNetworkError || web.isHttpError)
- {
- UnityLog.LogError("RequestDownData" + url);
- complete?.Invoke(null);
- }
- else
- {
- complete?.Invoke(web);
- }
- }
- }
- /// <summary>
- /// 从URl下载指定的资源
- /// </summary>
- /// <param name="url">资源的地址,可以是网络路径,也可以是本地文件路径</param>
- /// <param name="updateProcess">下载的进度,当前已下载文件大小,以及进度</param>
- /// <param name="complete"></param>
- /// <param name="form">请求的参数,如果为空代表Get请求,不为空代表Post请求</param>
- /// <returns></returns>
- public static IEnumerator RequestDownData(string url, Action<string, UnityWebRequest> complete, DownloadHandler hander = null, Action<float, float> updateProcess = null, WWWForm form = null)
- {
- UnityWebRequest web;
- Debug.Log("RequestDownData" + url);
- if (form == null)
- {
- web = UnityWebRequest.Get(url);
- }
- else
- {
- web = UnityWebRequest.Post(url, form);
- }
- if (hander != null)
- {
- web.downloadHandler = hander;
- }
- web.SendWebRequest();
- while (!web.isDone)
- {
- updateProcess?.Invoke(web.downloadedBytes, web.downloadProgress);
- yield return 0;
- }
- if (web.isDone)
- {
- updateProcess?.Invoke(web.downloadedBytes, 1);
- }
- if (web.isNetworkError || web.isHttpError)
- {
- complete?.Invoke(web.error, web);
- Debug.LogError(web.error + url);
- }
- else
- {
- complete?.Invoke(null, web);
- }
- web.Dispose();
- }
- /// <summary>
- /// 上传数据到服务端,并得到服务器返回的结果
- /// 与下面的RequestDownData类似,但是更新上传进度,适用于文件上传
- /// </summary>
- /// <param name="url"></param>
- /// <param name="form"></param>
- /// <param name="updateProcess"></param>
- /// <param name="complete"></param>
- /// <returns></returns>
- public static IEnumerator RequestUpLoadData(string url, WWWForm form, Action<float, float> updateProcess, Action<string, UnityWebRequest> complete)
- {
- UnityWebRequest web = UnityWebRequest.Post(url, form);
- web.SendWebRequest();
- while (!web.isDone)
- {
- updateProcess?.Invoke(web.uploadedBytes, web.uploadProgress);
- yield return 0;
- }
- if (web.isDone)
- {
- updateProcess?.Invoke(web.uploadedBytes, 1);
- }
- if (web.isNetworkError || web.isHttpError)
- {
- complete?.Invoke(web.error, web);
- }
- else
- {
- complete?.Invoke(null, web);
- }
- web.Dispose();
- }
- /// <summary>
- /// 是否是忽略的文件类型
- /// </summary>
- /// <param name="sug"></param>
- /// <returns></returns>
- public static bool isIgnoreExtension(string ignoreExtension, string suffix)
- {
- string[] igs = ignoreExtension.Split('|', ' ', ',');
- for (int i = 0; i < igs.Length; i++)
- {
- if (igs[i] == suffix)
- {
- return true;
- }
- }
- return false;
- }
- /// <summary>
- /// 保存文本文件到本地
- /// 同步方法
- /// </summary>
- public static bool SaveDataToFile(string path, string txt)
- {
- try
- {
- if (!string.IsNullOrEmpty(txt))
- {
- File.WriteAllText(path, txt);
- return true;
- }
- }
- catch (Exception ex)
- {
- UnityLog.LogError(path + ex.ToString());
- }
- return false;
- }
- /// <summary>
- /// 保存二进制字节文件到本地,同步方法
- /// </summary>
- /// <param name="path"></param>
- /// <param name="data"></param>
- public static bool SaveDataToFile(string path, byte[] data)
- {
- try
- {
- string dir = Path.GetDirectoryName(path);
- if (!Directory.Exists(dir))
- {
- Directory.CreateDirectory(dir);
- }
- FileStream fs = new FileStream(path, FileMode.Create);
- fs.Write(data, 0, data.Length);
- fs.Dispose();
- fs.Close();
- return true;
- }
- catch (Exception ex)
- {
- UnityLog.LogError(path + ex.ToString());
- }
- return false;
- }
- /// <summary>
- /// 异步保存文本文件
- /// </summary>
- /// <param name="path"></param>
- /// <param name="txt"></param>
- /// <param name="saveProcess"></param>
- /// <returns></returns>
- public static IEnumerator SaveDataToFile(string path, string txt, Action<float> saveProcess, Action<bool, string> onComplete)
- {
- yield return SaveDataToFile(path, Encoding.Default.GetBytes(txt), saveProcess, onComplete);
- }
- /// <summary>
- /// 保存二进制字节文件到本地,异步方法
- /// </summary>
- /// <param name="path"></param>
- /// <param name="data"></param>
- private static IEnumerator SaveDataToFile(string path, byte[] data, Action<float> saveProcess, Action<bool, string> onComplete)
- {
- bool isSuccess = false;
- if (data != null && data.Length > 0)
- {
- Task task = null;
- FileStream fs = null;
- float allData = data.Length;
- try
- {
- fs = new FileStream(path, FileMode.Create);
- task = fs.WriteAsync(data, 0, data.Length);
- isSuccess = true;
- }
- catch (Exception ex)
- {
- UnityLog.LogError(path + ex.ToString());
- path = ex.ToString();
- isSuccess = false;
- }
- float tmp = 0;
- float allTime = data.Length / WriteSpeed;
- ///预计存储完成的时间
- while (task != null && !task.IsCompleted)
- {
- if (tmp < allTime)
- {
- tmp += Time.deltaTime;
- }
- saveProcess?.Invoke(tmp / allTime);
- yield return 0;
- }
- saveProcess(1);
- fs.Dispose();
- fs.Close();
- }
- onComplete?.Invoke(isSuccess, path);
- }
- /// <summary>
- /// 广度优先,遍历文件
- /// </summary>
- /// <param name="path"></param>
- /// <param name="callBack"></param>
- public static void FindFileBreadth(string path, Action<string> callBack)
- {
- try
- {
- DirectoryInfo di = new DirectoryInfo(path);
- FileInfo[] fis = di.GetFiles();
- for (int i = 0; i < fis.Length; i++)
- {
- callBack?.Invoke(fis[i].FullName);
- }
- DirectoryInfo[] dis = di.GetDirectories();
- for (int j = 0; j < dis.Length; j++)
- {
- FindFileBreadth(dis[j].FullName, callBack);
- }
- }
- catch (Exception ex)
- {
- UnityLog.LogError(ex.ToString());
- }
- }
- /// <summary>
- /// 深度优先,遍历文件
- /// </summary>
- /// <param name="dir"></param>
- public static void FindFileByDepth(string dir, Action<string> callBack)
- {
- try
- {
- DirectoryInfo d = new DirectoryInfo(dir);
- FileSystemInfo[] fsinfos = d.GetFileSystemInfos();
- foreach (FileSystemInfo fsinfo in fsinfos)
- {
- if (fsinfo is DirectoryInfo)
- {
- FindFileByDepth(fsinfo.FullName, callBack);
- }
- else
- {
- callBack?.Invoke(fsinfo.FullName);
- }
- }
- }
- catch (Exception ex)
- {
- UnityLog.LogError(ex.ToString());
- }
- }
- /// <summary>
- /// 获取文件MD5值
- /// </summary>
- /// <param name="fileName">文件绝对路径</param>
- /// <returns>MD5值</returns>
- public static string GetMD5HashFromFile(string fileName)
- {
- try
- {
- FileStream file = new FileStream(fileName, FileMode.Open);
- System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
- byte[] retVal = md5.ComputeHash(file);
- file.Close();
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < retVal.Length; i++)
- {
- sb.Append(retVal[i].ToString("x2"));
- }
- return sb.ToString();
- }
- catch (Exception ex)
- {
- throw new Exception("GetMD5HashFromFile() fail,error:" + ex.Message);
- }
- }
- /// <summary>
- /// 重命名文件
- /// </summary>
- /// <param name="file"></param>
- /// <param name="newFile"></param>
- public static void ReNameFile(string file, string newFile)
- {
- if (File.Exists(file))
- {
- try
- {
- string dir = Path.GetDirectoryName(newFile);
- if (!Directory.Exists(dir))
- {
- Directory.CreateDirectory(dir);
- }
- if (File.Exists(newFile))
- {
- File.Delete(newFile);
- }
- FileInfo info = new FileInfo(file);
- info.MoveTo(newFile);
- }
- catch (Exception ex)
- {
- UnityLog.LogError(file + " is error" + ex.ToString());
- }
- }
- }
- /// <summary>
- /// 删除文件
- /// </summary>
- /// <param name="file"></param>
- /// <param name="newFile"></param>
- public static void DelFile(string file)
- {
- UnityLog.Log(file + " is Del", 3);
- if (File.Exists(file))
- {
- try
- {
- File.Delete(file);
- }
- catch (Exception ex)
- {
- UnityLog.LogError(file + " is error" + ex.ToString());
- }
- }
- }
- /// <summary>
- /// 拷贝文件
- /// </summary>
- /// <param name="SourcePath"></param>
- /// <param name="DestinationPath"></param>
- /// <param name="overwriteexisting">是否覆盖</param>
- /// <returns></returns>
- public static bool CopyDirectory(string SourcePath, string DestinationPath, bool overwriteexisting)
- {
- bool ret = false;
- try
- {
- SourcePath = SourcePath.EndsWith(@"\") ? SourcePath : SourcePath + @"\";
- DestinationPath = DestinationPath.EndsWith(@"\") ? DestinationPath : DestinationPath + @"\";
- if (Directory.Exists(SourcePath))
- {
- if (Directory.Exists(DestinationPath) == false)
- Directory.CreateDirectory(DestinationPath);
- foreach (string fls in Directory.GetFiles(SourcePath))
- {
- FileInfo flinfo = new FileInfo(fls);
- flinfo.CopyTo(DestinationPath + flinfo.Name, overwriteexisting);
- }
- foreach (string drs in Directory.GetDirectories(SourcePath))
- {
- DirectoryInfo drinfo = new DirectoryInfo(drs);
- if (CopyDirectory(drs, DestinationPath + drinfo.Name, overwriteexisting) == false)
- ret = false;
- }
- }
- ret = true;
- }
- catch (Exception ex)
- {
- ret = false;
- UnityLog.LogError(ex.ToString());
- }
- return ret;
- }
- /// <summary>
- /// 文件是否是图片
- /// </summary>
- /// <param name="fileName"></param>
- /// <returns></returns>
- public static bool IsMoviesFile(string fileName)
- {
- if (!string.IsNullOrEmpty(fileName))
- {
- string exten = Path.GetExtension(fileName);
- return IsMediaType(exten.ToUpper(), MoviesType);
- }
- return false;
- }
- public static bool IsTextureFile(string fileName)
- {
- if (!string.IsNullOrEmpty(fileName))
- {
- string exten = Path.GetExtension(fileName);
- return IsMediaType(exten.ToUpper(), TexturesType);
- }
- return false;
- }
- /// <summary>
- /// 判断是否是音频文件
- /// MP3,WAV等
- /// </summary>
- /// <param name="fileName"></param>
- /// <returns></returns>
- public static bool IsAudioFile(string fileName)
- {
- if (!string.IsNullOrEmpty(fileName))
- {
- string exten = Path.GetExtension(fileName);
- return IsMediaType(exten.ToUpper(), AudiosType);
- }
- return false;
- }
- /// <summary>
- /// 是否是多媒体文件:图片,视频,音频
- /// </summary>
- /// <param name="fileName"></param>
- /// <param name="types"></param>
- /// <returns></returns>
- public static bool IsMediaType(string fileName, string[] types)
- {
- if (!string.IsNullOrEmpty(fileName) && types != null)
- {
- for (int i = 0; i < types.Length; i++)
- {
- if (TexturesType[i] == fileName)
- {
- return true;
- }
- }
- }
- return false;
- }
- /// <summary>
- /// 是否多媒体文件
- /// 音频,视频,图片
- /// </summary>
- /// <param name="fileName"></param>
- /// <returns></returns>
- public static bool IsMediaType(string fileName)
- {
- if (!string.IsNullOrEmpty(fileName))
- {
- string exten = Path.GetExtension(fileName);
- exten = exten.ToUpper();
- return IsMediaType(exten, TexturesType) || IsMediaType(exten, MoviesType) || IsMediaType(exten, AudiosType);
- }
- return false;
- }
- /// <summary>
- /// 是否存在某文件
- /// </summary>
- /// <param name="file"></param>
- /// <returns></returns>
- public static bool Exists(string file)
- {
- return File.Exists(file);
- }
- }
- }
|