最近在开发时遇到了个小挑战——如何准确判断一个文件是否是真的图片?这可不是小事,我的程序是一个有关买卖的可支付软件,弄不好可能要赔钱的,如果被人黑了不只挣不到钱还可能把客户的钱转走。岂不害死我?!

要知道仅仅通过检查文件后缀名(如 j p g、p n g 等)是不行的,因为用户可以轻易地修改这些后缀名来伪装文件。网上经常小黑门通过更改文件扩展名上传自己的小马的。
所以这个需求听起来简单,实则让人头疼!

我当时接到这个任务的时候还觉得太简单了,去找现成的类或方法可以快速辨别一个文件是否为真正的图片不就可以了?通过简单的代码行就可以识别就行了?!
但是,经过百度一番查查查和尝试,发现竟然找不到这样的“一键判定”功能!找到的代码不是不能运行就是用别的语言写的,我也不是神仙呀,有的不会用,况且也不一定是对的,费了半天也找不到,最终只好自己来写了.
第一步,先判断一下是不是图片的扩展名,不是的直接淘汰掉.
public static Boolean IsImageByName(string name)
{
int pos = name.LastIndexOf(".");
if (name.Length - pos - 1 < 3)
{
return false;
}
//string ext = name.Substring(pos + 1, name.Length - pos - 1);
//return ext.IsInIgnoreCase("jpg", "png", "gif", "bmp", "TIFF", "tif", "psd");
string kzm = Path.GetExtension(name).ToLower();
if (kzm == ".jpg" || kzm == ".png" || kzm == ".bmp" || kzm == ".gif" || kzm == ".tif" || kzm == ".tiff" || kzm == ".psd")
{
return true;
}
return false;
}
实现的逻辑是:
首先通过调用 name.LastIndexOf(".") 查找文件名中最后一个.的位置,也就是文件扩展名的开始。
检查从该点到最后一个字符的距离(即扩展名长度),如果长度小于3,则认为这不是一个有效的图像文件扩展名,并返回 false。
如果扩展名长度至少为3个字符,使用 Path.GetExtension(name) 方法获取文件的扩展名并将结果转换为小写(.ToLower())。
然后将得到的小写扩展名与预定义的图像文件扩展名进行比较,包括:.jpg, .png, .bmp, .gif, .tif, .tiff, 和 .psd。
如果找到匹配的图像扩展名,则返回 true,表示输入的文件名代表的是某种支持的图像文件类型;否则,返回 false。
这个方法可以有效地检查一个字符串是否为指定图像格式的文件名,如果不是直接PASS.这样不用后面做多余的判断了。
第二步,通过第一步断定文件名看起来像是一个图片文件,再尝试从文件路径加载该图片来判断。

public static Boolean IsImage(string path)
{
try
{
Boolean istrueimg = IsImageByName(path);
if (istrueimg)
{
System.Drawing.Image img = System.Drawing.Image.FromFile(path);
return true;
}
}
catch (Exception)
{
return false;
}
return false;
}
这个很简单了吧,关键代码:
System.Drawing.Image img = System.Drawing.Image.FromFile(path);

你还有更好的方法吗?我这个怎么样?