JAVA开发小技巧--读取文件魔数来识别文件类型
我们在开发应用软件的时候一定会涉及到文件上传的功能,并且我们还要对用户上传文件的合法性进行校验。在文件校验的时候,我们通常会通过文件的后缀名去校验该文件是否合法,但是这样校验就会有一个弊端:如果用户上传的文件是改过文件名后缀的文件该怎么办呢 ?(比如某个上传接口只允许上传图片,那么如果我把一个 .txt 文件的后缀改成 .jpg ,那么就可以绕过文件的后缀名校验方法 )俗话说“繁琐问题必有猥琐解法”,那么今天就给各位小伙伴介绍另外一种文件校验方式 —— 通过文件魔数值进行校验。
魔数这个词在不同领域代表不同的含义。在计算机领域,魔数有两个含义,一指用来判断文件类型的魔数;二指程序代码中的魔数,也称魔法值。
我们今天所说的魔数就是表示不同文件类型的魔术数字,它指定是文件的最开头的几个用于唯一区别其它文件类型的字节,有了这些魔术数字,我们就可以很方便的区别不同的文件,这也使得编程变得更加容易,减少了我们用于区别一个文件的文件类型所要花费的时间 。关于文件校验也没有什么需要过多阐述的东西,下面就直接上代码
/**
* 利用文件魔数值判断文件类型
*/
public class FileMagicUtils {
/**
* 缓存文件魔数值
*/
public static final HashMap<String, String> mFileTypes = new HashMap<>();
static {
mFileTypes.put("jpg", "FFD8FFE0");
mFileTypes.put("png", "89504E47");
mFileTypes.put("gif", "47494638");
mFileTypes.put("tif", "49492A00");
mFileTypes.put("bmp", "424D");
mFileTypes.put("psd", "38425053");
mFileTypes.put("xml", "3C3F786D6C");
mFileTypes.put("html", "68746D6C3E");
mFileTypes.put("doc", "D0CF11E0");
mFileTypes.put("mdb", "5374616E64617264204A");
mFileTypes.put("pdf", "255044462D312E");
mFileTypes.put("docx", "504B0304");
mFileTypes.put("rar", "52617221");
mFileTypes.put("avi", "41564920");
}
/**
* 获取文件魔数值
* @param file 对应文件
* @return 16进制魔数值
*/
private static String getMagicNumber(File file) {
byte[] bytes = new byte[20];
try (FileInputStream inputStream = new FileInputStream(file)) {
inputStream.read(bytes, 0, 20);
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
// b & 0xFF转16禁止。
sb.append(Integer.toHexString(b & 0xFF));
}
return sb.toString().toUpperCase();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 判断单个文件的后缀名
* @param file 文件
* @param fileSuffix 需要判断的文件后缀名
*/
public static boolean isAllowedExtension(File file, String fileSuffix){
String magicNumber = getMagicNumber(file);
System.out.println(magicNumber);
return magicNumber.startsWith(mFileTypes.get(fileSuffix));
}
/**
* 判断单个文件的后缀名是否在一个范围
* @param file 文件
* @param fileSuffixs 需要判断的文件后缀名
*/
public static boolean isAllowedExtension(File file, String... fileSuffixs){
String magicNumber = getMagicNumber(file);
System.out.println(magicNumber);
boolean temp = false;
for (String fileSuffix : fileSuffixs) {
if(magicNumber.startsWith(mFileTypes.get(fileSuffix))){
temp = true;
}
}
return temp;
}
public static void main(String[] args) {
System.out.println(isAllowedExtension(new File("D:\\图片1.png"), "png", "jpg"));
}
}运行结果
方法很简单,没有什么复杂的逻辑,唯一需要注意的就是:代码中罗列出的文件魔数值都是一些常用的文件所对应的魔数值,如果有特殊的文件需要校验的话,可以先跑一次校验工具,获取到对应的魔数值以后,将魔数值加到 HashMap 中就可以正常使用。
版权声明
非特殊说明,本文由Zender原创或收集发布,欢迎转载。
上一篇:分类树菜单优化 下一篇:Java项目防止SQL注入4总方式
ZENDER


发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。