VerifyFileExtensionName.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. // 大名科技(天津)有限公司 版权所有
  2. //
  3. // 此源代码遵循位于源代码树根目录中的 LICENSE 文件的许可证
  4. //
  5. // 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动
  6. //
  7. // 任何基于本项目二次开发而产生的一切法律纠纷和责任,均与作者无关
  8. namespace Admin.NET.Core;
  9. /// <summary>
  10. /// 验证文件类型
  11. /// </summary>
  12. public static class VerifyFileExtensionName
  13. {
  14. private static readonly IDictionary<string, string> dics_ext = new Dictionary<string, string>();
  15. private static readonly IDictionary<string, HashSet<int>> ext_dics = new Dictionary<string, HashSet<int>>();
  16. static VerifyFileExtensionName()
  17. {
  18. dics_ext.Add("FFD8FFE0", ".jpg");
  19. dics_ext.Add("89504E47", ".png");
  20. dics_ext.Add("47494638", ".gif");
  21. dics_ext.Add("49492A00", ".tif");
  22. dics_ext.Add("424D", ".bmp");
  23. // PS和CAD
  24. dics_ext.Add("38425053", ".psd");
  25. dics_ext.Add("41433130", ".dwg"); // CAD
  26. dics_ext.Add("252150532D41646F6265", ".ps");
  27. // 办公文档类
  28. dics_ext.Add("D0CF11E0", ".doc"); // ppt、doc、xls
  29. dics_ext.Add("504B0304", ".docx"); // pptx、docx、xlsx
  30. /* 注意由于文本文档录入内容过多,则读取文件头时较为多变-START */
  31. dics_ext.Add("0D0A0D0A", ".txt"); // txt
  32. dics_ext.Add("0D0A2D2D", ".txt"); // txt
  33. dics_ext.Add("0D0AB4B4", ".txt"); // txt
  34. dics_ext.Add("B4B4BDA8", ".txt"); // 文件头部为汉字
  35. dics_ext.Add("73646673", ".txt"); // txt,文件头部为英文字母
  36. dics_ext.Add("32323232", ".txt"); // txt,文件头部内容为数字
  37. dics_ext.Add("0D0A09B4", ".txt"); // txt,文件头部内容为数字
  38. dics_ext.Add("3132330D", ".txt"); // txt,文件头部内容为数字
  39. /* 注意由于文本文档录入内容过多,则读取文件头时较为多变-END */
  40. dics_ext.Add("7B5C727466", ".rtf"); // 日记本
  41. dics_ext.Add("255044462D312E", ".pdf");
  42. // 视频或音频类
  43. dics_ext.Add("3026B275", ".wma");
  44. dics_ext.Add("57415645", ".wav");
  45. dics_ext.Add("41564920", ".avi");
  46. dics_ext.Add("4D546864", ".mid");
  47. dics_ext.Add("2E524D46", ".rm");
  48. dics_ext.Add("000001BA", ".mpg");
  49. dics_ext.Add("000001B3", ".mpg");
  50. dics_ext.Add("6D6F6F76", ".mov");
  51. dics_ext.Add("3026B2758E66CF11", ".asf");
  52. // 压缩包
  53. dics_ext.Add("52617221", ".rar");
  54. dics_ext.Add("504B03040A000000", ".zip");
  55. dics_ext.Add("1F8B08", ".gz");
  56. // 程序文件
  57. dics_ext.Add("3C3F786D6C", ".xml");
  58. dics_ext.Add("68746D6C3E", ".html");
  59. //dics_ext.Add("7061636B", ".java");
  60. //dics_ext.Add("3C254020", ".jsp");
  61. //dics_ext.Add("4D5A9000", ".exe");
  62. dics_ext.Add("44656C69766572792D646174653A", ".eml"); // 邮件
  63. dics_ext.Add("5374616E64617264204A", ".mdb"); // Access数据库文件
  64. dics_ext.Add("46726F6D", ".mht");
  65. dics_ext.Add("4D494D45", ".mhtml");
  66. foreach (var dics in dics_ext)
  67. {
  68. if (!ext_dics.ContainsKey(dics.Value))
  69. ext_dics.Add(dics.Value, new HashSet<int> { dics.Key.Length / 2 });
  70. else
  71. ext_dics[dics.Value].Add(dics.Key.Length / 2);
  72. }
  73. }
  74. /// <summary>
  75. /// 文件格式和文件内容格式是否一致
  76. /// </summary>
  77. /// <param name="stream"></param>
  78. /// <param name="suffix"></param>
  79. /// <returns></returns>
  80. public static bool IsSameType(Stream stream, string suffix = ".jpg")
  81. {
  82. if (stream == null)
  83. return false;
  84. suffix = suffix.ToLower();
  85. if (!ext_dics.ContainsKey(suffix))
  86. return false;
  87. try
  88. {
  89. foreach (var Len in ext_dics[suffix])
  90. {
  91. byte[] b = new byte[Len];
  92. stream.Read(b, 0, b.Length);
  93. // string fileType = System.Text.Encoding.UTF8.GetString(b);
  94. string fileKey = GetFileHeader(b);
  95. if (dics_ext.ContainsKey(fileKey))
  96. return true;
  97. }
  98. }
  99. catch (IOException)
  100. {
  101. }
  102. return false;
  103. }
  104. /**
  105. * 根据文件转换成的字节数组获取文件头信息
  106. * @param 文件路径
  107. * @return 文件头信息
  108. */
  109. private static string GetFileHeader(byte[] b)
  110. {
  111. string value = BytesToHexString(b);
  112. return value;
  113. }
  114. /**
  115. * 将要读取文件头信息的文件的byte数组转换成string类型表示
  116. * 下面这段代码就是用来对文件类型作验证的方法,
  117. * 将字节数组的前四位转换成16进制字符串,并且转换的时候,要先和0xFF做一次与运算。
  118. * 这是因为,整个文件流的字节数组中,有很多是负数,进行了与运算后,可以将前面的符号位都去掉,
  119. * 这样转换成的16进制字符串最多保留两位,如果是正数又小于10,那么转换后只有一位,
  120. * 需要在前面补0,这样做的目的是方便比较,取完前四位这个循环就可以终止了
  121. * @param src要读取文件头信息的文件的byte数组
  122. * @return 文件头信息
  123. */
  124. private static string BytesToHexString(byte[] src)
  125. {
  126. var builder = new StringBuilder();
  127. if (src == null || src.Length <= 0)
  128. return null;
  129. string hv;
  130. for (int i = 0; i < src.Length; i++)
  131. {
  132. // 以十六进制(基数 16)无符号整数形式返回一个整数参数的字符串表示形式,并转换为大写
  133. hv = Convert.ToString(src[i] & 0xFF, 16).ToUpper();
  134. if (hv.Length < 2)
  135. builder.Append(0);
  136. builder.Append(hv);
  137. }
  138. return builder.ToString();
  139. }
  140. }