using System; using System.IO; using System.Threading.Tasks; namespace Masuit.Tools.Files { /// /// 大文件操作扩展类 /// public static class FileExt { /// /// 以文件流的形式复制大文件 /// /// 源 /// 目标地址 /// 缓冲区大小,默认8MB public static void CopyToFile(this Stream fs, string dest, int bufferSize = 1024 * 8 * 1024) { using (FileStream fsWrite = new FileStream(dest, FileMode.OpenOrCreate, FileAccess.ReadWrite)) { byte[] buf = new byte[bufferSize]; int len = 0; while ((len = fs.Read(buf, 0, buf.Length)) != 0) { fsWrite.Write(buf, 0, len); } } } /// /// 以文件流的形式复制大文件(异步方式) /// /// 源 /// 目标地址 /// 缓冲区大小,默认8MB public static async void CopyToFileAsync(this Stream fs, string dest, int bufferSize = 1024 * 1024 * 8) { using (FileStream fsWrite = new FileStream(dest, FileMode.OpenOrCreate, FileAccess.ReadWrite)) { byte[] buf = new byte[bufferSize]; int len = 0; await Task.Run(() => { using (fs) { while ((len = fs.Read(buf, 0, buf.Length)) != 0) { fsWrite.Write(buf, 0, len); } } }).ConfigureAwait(true); } } /// /// 计算文件的 MD5 值 /// /// 源文件流 /// MD5 值16进制字符串 public static string GetFileMD5(this FileStream fs) => HashFile(fs, "md5"); /// /// 计算文件的 MD5 值 /// /// 源文件流 /// MD5 值16进制字符串 public static Task GetFileMD5Async(this FileStream fs) => HashFileAsync(fs, "md5"); /// /// 计算文件的 sha1 值 /// /// 源文件流 /// sha1 值16进制字符串 public static string GetFileSha1(this Stream fs) => HashFile(fs, "sha1"); /// /// 计算文件的 sha1 值 /// /// 源文件流 /// sha1 值16进制字符串 public static Task GetFileSha1Async(this FileStream fs) => HashFileAsync(fs, "sha1"); /// /// 计算文件的哈希值 /// /// 被操作的源数据流 /// 算法:sha1,md5 /// 哈希值16进制字符串 private static string HashFile(Stream fs, string algName) { byte[] hashBytes = HashData(fs, algName); return ByteArrayToHexString(hashBytes); } /// /// 计算文件的哈希值 /// /// 被操作的源数据流 /// 算法:sha1,md5 /// 哈希值16进制字符串 private static async Task HashFileAsync(Stream fs, string algName) { byte[] hashBytes = await HashDataAsync(fs, algName).ConfigureAwait(false); return ByteArrayToHexString(hashBytes); } /// /// 计算哈希值 /// /// 要计算哈希值的 Stream /// 算法:sha1,md5 /// 哈希值字节数组 private static byte[] HashData(System.IO.Stream stream, string algName) { System.Security.Cryptography.HashAlgorithm algorithm; if (algName == null) { throw new ArgumentNullException("algName 不能为 null"); } if (string.Compare(algName, "sha1", true) == 0) { algorithm = System.Security.Cryptography.SHA1.Create(); } else { if (string.Compare(algName, "md5", true) != 0) { throw new Exception("algName 只能使用 sha1 或 md5"); } algorithm = System.Security.Cryptography.MD5.Create(); } return algorithm.ComputeHash(stream); } /// /// 计算哈希值 /// /// 要计算哈希值的 Stream /// 算法:sha1,md5 /// 哈希值字节数组 private static async Task HashDataAsync(this Stream stream, string algName) { System.Security.Cryptography.HashAlgorithm algorithm; if (algName == null) { throw new ArgumentNullException("algName 不能为 null"); } if (string.Compare(algName, "sha1", true) == 0) { algorithm = System.Security.Cryptography.SHA1.Create(); } else { if (string.Compare(algName, "md5", true) != 0) { throw new Exception("algName 只能使用 sha1 或 md5"); } algorithm = System.Security.Cryptography.MD5.Create(); } return await Task.Run(() => algorithm.ComputeHash(stream)).ConfigureAwait(false); } /// /// 字节数组转换为16进制表示的字符串 /// private static string ByteArrayToHexString(byte[] buf) => BitConverter.ToString(buf).Replace("-", ""); } }