FileExt.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. using System.IO;
  2. using System.Security.Cryptography;
  3. using System.Text;
  4. using System.Threading.Tasks;
  5. namespace Masuit.Tools.Files
  6. {
  7. /// <summary>
  8. /// 大文件操作扩展类
  9. /// </summary>
  10. public static class FileExt
  11. {
  12. /// <summary>
  13. /// 以文件流的形式复制大文件
  14. /// </summary>
  15. /// <param name="fs">源</param>
  16. /// <param name="dest">目标地址</param>
  17. /// <param name="bufferSize">缓冲区大小,默认8MB</param>
  18. public static void CopyToFile(this Stream fs, string dest, int bufferSize = 1024 * 8 * 1024)
  19. {
  20. fs.Seek(0, SeekOrigin.Begin);
  21. using var fsWrite = new FileStream(dest, FileMode.OpenOrCreate, FileAccess.ReadWrite);
  22. var stream = new BufferedStream(fs, bufferSize);
  23. stream.CopyTo(fsWrite);
  24. fs.Seek(0, SeekOrigin.Begin);
  25. }
  26. /// <summary>
  27. /// 以文件流的形式复制大文件(异步方式)
  28. /// </summary>
  29. /// <param name="fs">源</param>
  30. /// <param name="dest">目标地址</param>
  31. /// <param name="bufferSize">缓冲区大小,默认8MB</param>
  32. public static Task CopyToFileAsync(this Stream fs, string dest, int bufferSize = 1024 * 1024 * 8)
  33. {
  34. using var fsWrite = new FileStream(dest, FileMode.OpenOrCreate, FileAccess.ReadWrite);
  35. var stream = new BufferedStream(fs, bufferSize);
  36. return stream.CopyToAsync(fsWrite);
  37. }
  38. /// <summary>
  39. /// 将内存流转储成文件
  40. /// </summary>
  41. /// <param name="ms"></param>
  42. /// <param name="filename"></param>
  43. public static void SaveFile(this Stream ms, string filename)
  44. {
  45. ms.Seek(0, SeekOrigin.Begin);
  46. var dir = Path.GetDirectoryName(filename);
  47. if (!Directory.Exists(dir))
  48. {
  49. Directory.CreateDirectory(dir);
  50. }
  51. using var fs = new FileStream(filename, FileMode.Create, FileAccess.Write);
  52. var stream = new BufferedStream(ms, 1048576);
  53. stream.CopyTo(fs);
  54. ms.Seek(0, SeekOrigin.Begin);
  55. }
  56. /// <summary>
  57. /// 将内存流转储成文件
  58. /// </summary>
  59. /// <param name="ms"></param>
  60. /// <param name="filename"></param>
  61. public static async Task SaveFileAsync(this Stream ms, string filename)
  62. {
  63. ms.Seek(0, SeekOrigin.Begin);
  64. var dir = Path.GetDirectoryName(filename);
  65. if (!Directory.Exists(dir))
  66. {
  67. Directory.CreateDirectory(dir);
  68. }
  69. using var fs = new FileStream(filename, FileMode.Create, FileAccess.Write);
  70. var stream = new BufferedStream(ms, 1048576);
  71. await stream.CopyToAsync(fs);
  72. ms.Seek(0, SeekOrigin.Begin);
  73. }
  74. /// <summary>
  75. /// 计算文件的 MD5 值
  76. /// </summary>
  77. /// <param name="fs">源文件流</param>
  78. /// <returns>MD5 值16进制字符串</returns>
  79. public static string GetFileMD5(this FileStream fs) => HashFile(fs);
  80. /// <summary>
  81. /// 计算文件的 sha1 值
  82. /// </summary>
  83. /// <param name="fs">源文件流</param>
  84. /// <returns>sha1 值16进制字符串</returns>
  85. public static string GetFileSha1(this Stream fs) => HashFile(fs, nameof(SHA1));
  86. /// <summary>
  87. /// 计算文件的 sha256 值
  88. /// </summary>
  89. /// <param name="fs">源文件流</param>
  90. /// <returns>sha256 值16进制字符串</returns>
  91. public static string GetFileSha256(this Stream fs) => HashFile(fs, nameof(SHA256));
  92. /// <summary>
  93. /// 计算文件的 sha512 值
  94. /// </summary>
  95. /// <param name="fs">源文件流</param>
  96. /// <returns>sha512 值16进制字符串</returns>
  97. public static string GetFileSha512(this Stream fs) => HashFile(fs, nameof(SHA512));
  98. /// <summary>
  99. /// 计算文件的哈希值
  100. /// </summary>
  101. /// <param name="fs">被操作的源数据流</param>
  102. /// <param name="algo">加密算法</param>
  103. /// <returns>哈希值16进制字符串</returns>
  104. private static string HashFile(Stream fs, string algo = nameof(MD5))
  105. {
  106. fs.Seek(0, SeekOrigin.Begin);
  107. using HashAlgorithm crypto = algo switch
  108. {
  109. nameof(SHA1) => SHA1.Create(),
  110. nameof(SHA256) => SHA256.Create(),
  111. nameof(SHA512) => SHA512.Create(),
  112. _ => MD5.Create(),
  113. };
  114. var stream = new BufferedStream(fs, 1048576);
  115. byte[] hash = crypto.ComputeHash(stream);
  116. var sb = new StringBuilder();
  117. foreach (var t in hash)
  118. {
  119. sb.Append(t.ToString("x2"));
  120. }
  121. fs.Seek(0, SeekOrigin.Begin);
  122. return sb.ToString();
  123. }
  124. }
  125. }