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
{
///
/// 文件工具类
/// 下载,写入文件,断点续传,边下边存
/// 遍历,拷贝文件
/// 获取文件的MD5等
///
public class DataFileUtil
{
///
/// 预估的写入文件的速度,与真实速度无关,仅仅是模拟评估,预计写入用时
///
public const float WriteSpeed = 1024 * 1024 * 150f;
/////
///// 写入缓存的大小,如果越小,可能会引起卡顿(频繁访问数据)
/////
//public const int CacheSave = 1024 * 1024 * 2;
///
/// 图片格式
///
public static string[] TexturesType = new string[] { "BMP", "EXR", "GIF", "HDR", "IFF", "JPG", "PICT", "PNG", "PSD", "TGA", "TIFF" };
///
/// 视频格式
///
public static string[] MoviesType = new string[] { "MOV", "MPG", "MP4", "AVI", "ASF" };
///
/// 音频格式
///
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";
/////
///// 断点下载,异步读写
/////
/////
/////
/////
/////
/////
/////
//public static IEnumerator DownLoadDataAsync(string url, string path,
// Action completeData, DownloadHandler hander = null, Action downLoadProcess = null)
//{
// yield return 0;
//}
///
/// 下载数据到本地,并将下载的数据返回给到上层应用
/// 此下载仅应用于可缓存的资源,图片文本等下载,大文件的下载请使用断点下载
///
///
///
///
///
///
///
public static IEnumerator DownLoadData(string url, string path,
Action completeData, DownloadHandler hander = null, Action 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();
}
///
/// 请求后台数据接口
///
///
public static IEnumerator RequestData(string url, Action reqComplete, bool isPost = true,
Dictionary header = null, Dictionary 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();
}
}
}
///
/// 获取资源的大小
///
///
///
///
public static IEnumerator GetDataSize(string url, Action getLen)
{
var headRequest = UnityWebRequest.Head(url);
yield return headRequest.SendWebRequest();
getLen?.Invoke(long.Parse(headRequest.GetResponseHeader("Content-Length")));
headRequest.Dispose();
}
///
/// 断点续传
/// 下载大文件请使用此函数
/// 注意,请自行检查是否已下载过此文件,此函数不再检查,直接执行下载
///
///
///
///
///
///
///
public static IEnumerator DownLoadDataAsync(string url, string path,
Action completeData, DownloadHandler hander = null, Action 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);
});
}
///
/// Get请求下载数据,断点下载,边下载边返回数据进行存储
///
/// url
/// 返回获取的数据
/// 文件的总大小
/// 已下载的数据
///
public static IEnumerator RequestDownData(string url, Action downData, long allLen, long downedLength = 0,
Action 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);
}
}
}
///
/// 从URl下载指定的资源
///
/// 资源的地址,可以是网络路径,也可以是本地文件路径
/// 下载的进度,当前已下载文件大小,以及进度
///
/// 请求的参数,如果为空代表Get请求,不为空代表Post请求
///
public static IEnumerator RequestDownData(string url, Action complete, DownloadHandler hander = null, Action 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();
}
///
/// 上传数据到服务端,并得到服务器返回的结果
/// 与下面的RequestDownData类似,但是更新上传进度,适用于文件上传
///
///
///
///
///
///
public static IEnumerator RequestUpLoadData(string url, WWWForm form, Action updateProcess, Action 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();
}
///
/// 是否是忽略的文件类型
///
///
///
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;
}
///
/// 保存文本文件到本地
/// 同步方法
///
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;
}
///
/// 保存二进制字节文件到本地,同步方法
///
///
///
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;
}
///
/// 异步保存文本文件
///
///
///
///
///
public static IEnumerator SaveDataToFile(string path, string txt, Action saveProcess, Action onComplete)
{
yield return SaveDataToFile(path, Encoding.Default.GetBytes(txt), saveProcess, onComplete);
}
///
/// 保存二进制字节文件到本地,异步方法
///
///
///
private static IEnumerator SaveDataToFile(string path, byte[] data, Action saveProcess, Action 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);
}
///
/// 广度优先,遍历文件
///
///
///
public static void FindFileBreadth(string path, Action 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());
}
}
///
/// 深度优先,遍历文件
///
///
public static void FindFileByDepth(string dir, Action 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());
}
}
///
/// 获取文件MD5值
///
/// 文件绝对路径
/// MD5值
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);
}
}
///
/// 重命名文件
///
///
///
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());
}
}
}
///
/// 删除文件
///
///
///
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());
}
}
}
///
/// 拷贝文件
///
///
///
/// 是否覆盖
///
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;
}
///
/// 文件是否是图片
///
///
///
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;
}
///
/// 判断是否是音频文件
/// MP3,WAV等
///
///
///
public static bool IsAudioFile(string fileName)
{
if (!string.IsNullOrEmpty(fileName))
{
string exten = Path.GetExtension(fileName);
return IsMediaType(exten.ToUpper(), AudiosType);
}
return false;
}
///
/// 是否是多媒体文件:图片,视频,音频
///
///
///
///
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;
}
///
/// 是否多媒体文件
/// 音频,视频,图片
///
///
///
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;
}
///
/// 是否存在某文件
///
///
///
public static bool Exists(string file)
{
return File.Exists(file);
}
}
}