You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

162 lines
6.2 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System.Text;
namespace Common.Util
{
/// <summary>
/// 验证文件类型
/// </summary>
public static class VerifyFileExtensionName
{
private static readonly IDictionary<string, string> dics_ext = new Dictionary<string, string>();
private static readonly IDictionary<string, HashSet<int>> ext_dics = new Dictionary<string, HashSet<int>>();
static VerifyFileExtensionName()
{
dics_ext.Add("FFD8FFE0", ".jpg");
dics_ext.Add("FFD8FFE1", ".jpg");
dics_ext.Add("89504E47", ".png");
dics_ext.Add("47494638", ".gif");
dics_ext.Add("49492A00", ".tif");
dics_ext.Add("424D", ".bmp");
// PS和CAD
dics_ext.Add("38425053", ".psd");
dics_ext.Add("41433130", ".dwg"); // CAD
dics_ext.Add("252150532D41646F6265", ".ps");
// 办公文档类
dics_ext.Add("D0CF11E0", ".ppt,.doc,.xls"); // ppt、doc、xls
dics_ext.Add("504B0304", ".pptx,.docx,.xlsx"); // pptx、docx、xlsx
/* 注意由于文本文档录入内容过多,则读取文件头时较为多变-START */
dics_ext.Add("0D0A0D0A", ".txt"); // txt
dics_ext.Add("0D0A2D2D", ".txt"); // txt
dics_ext.Add("0D0AB4B4", ".txt"); // txt
dics_ext.Add("B4B4BDA8", ".txt"); // 文件头部为汉字
dics_ext.Add("73646673", ".txt"); // txt,文件头部为英文字母
dics_ext.Add("32323232", ".txt"); // txt,文件头部内容为数字
dics_ext.Add("0D0A09B4", ".txt"); // txt,文件头部内容为数字
dics_ext.Add("3132330D", ".txt"); // txt,文件头部内容为数字
/* 注意由于文本文档录入内容过多,则读取文件头时较为多变-END */
dics_ext.Add("7B5C727466", ".rtf"); // 日记本
dics_ext.Add("255044462D312E", ".pdf");
// 视频或音频类
dics_ext.Add("3026B275", ".wma");
dics_ext.Add("57415645", ".wav");
dics_ext.Add("41564920", ".avi");
dics_ext.Add("4D546864", ".mid");
dics_ext.Add("2E524D46", ".rm");
dics_ext.Add("000001BA", ".mpg");
dics_ext.Add("000001B3", ".mpg");
dics_ext.Add("6D6F6F76", ".mov");
dics_ext.Add("3026B2758E66CF11", ".asf");
// 压缩包
dics_ext.Add("52617221", ".rar");
dics_ext.Add("504B03040A000000", ".zip");
dics_ext.Add("1F8B08", ".gz");
// 程序文件
dics_ext.Add("3C3F786D6C", ".xml");
dics_ext.Add("68746D6C3E", ".html");
//dics_ext.Add("7061636B", ".java");
//dics_ext.Add("3C254020", ".jsp");
//dics_ext.Add("4D5A9000", ".exe");
dics_ext.Add("44656C69766572792D646174653A", ".eml"); // 邮件
dics_ext.Add("5374616E64617264204A", ".mdb"); // Access数据库文件
dics_ext.Add("46726F6D", ".mht");
dics_ext.Add("4D494D45", ".mhtml");
foreach (var dics in dics_ext)
{
foreach (var ext in dics.Value.Split(","))
{
if (!ext_dics.ContainsKey(ext))
ext_dics.Add(ext, new HashSet<int> { dics.Key.Length / 2 });
else
ext_dics[ext].Add(dics.Key.Length / 2);
}
}
}
/// <summary>
/// 文件格式和文件内容格式是否一致
/// </summary>
/// <param name="stream"></param>
/// <param name="suffix"></param>
/// <returns></returns>
public static bool IsSameType(Stream stream, string suffix = ".jpg")
{
if (stream == null)
return false;
suffix = suffix.ToLower();
if (!ext_dics.ContainsKey(suffix))
return false;
try
{
foreach (var Len in ext_dics[suffix])
{
byte[] b = new byte[Len];
stream.Read(b, 0, b.Length);
// string fileType = System.Text.Encoding.UTF8.GetString(b);
string fileKey = GetFileHeader(b);
if (dics_ext.ContainsKey(fileKey))
return true;
}
}
catch (IOException)
{
}
return false;
}
/**
* 根据文件转换成的字节数组获取文件头信息
* @param 文件路径
* @return 文件头信息
*/
private static string GetFileHeader(byte[] b)
{
string value = BytesToHexString(b);
return value;
}
/**
* 将要读取文件头信息的文件的byte数组转换成string类型表示
* 下面这段代码就是用来对文件类型作验证的方法,
* 将字节数组的前四位转换成16进制字符串并且转换的时候要先和0xFF做一次与运算。
* 这是因为,整个文件流的字节数组中,有很多是负数,进行了与运算后,可以将前面的符号位都去掉,
* 这样转换成的16进制字符串最多保留两位如果是正数又小于10那么转换后只有一位
* 需要在前面补0这样做的目的是方便比较取完前四位这个循环就可以终止了
* @param src要读取文件头信息的文件的byte数组
* @return 文件头信息
*/
private static string BytesToHexString(byte[] src)
{
var builder = new StringBuilder();
if (src == null || src.Length <= 0)
return null;
string hv;
for (int i = 0; i < src.Length; i++)
{
// 以十六进制(基数 16无符号整数形式返回一个整数参数的字符串表示形式并转换为大写
hv = Convert.ToString(src[i] & 0xFF, 16).ToUpper();
if (hv.Length < 2)
builder.Append(0);
builder.Append(hv);
}
return builder.ToString();
}
}
}