Java通过魔数判断上传⽂件的类型
前⾔(转blog.csdn/t894690230/article/details/51242110)
⽂件上传功能是很多⽹站都必须的功能,⽽判断⽂件类型不仅可以过滤⽂件的上传,同时也能防范⽤户上传恶意的可执⾏⽂件和脚本,以及将⽂件上传服务器当作免费的⽂件存储服务器使⽤。
⽽对于上传⽂件来说,不能简单的通过后缀名来判断⽂件的类型,因为恶意攻击可以将可执⾏⽂件的后缀名称改为图⽚或者其他格式,诱导⽤户执⾏,因此,判断上传⽂件的类型需要更安全的⽅式。
与Java的class⽂件类似,很多类型的⽂件,起始的⼏个字节内容都是固定的,跟据这⼏个字节的内容,就可以判断⽂件的类型,这⼏个字节也被称为“魔数”,⽐如class⽂件的魔数就是“CAFEBABE”。
通过魔数判断⽂件类型便是⼀种更安全的⽅式,其⽰例源码如下。
1.新建⼀个⽂件类型的枚举类
public enum FileType {
/** JPEG */
JPEG("FFD8FF"),
/** PNG */16进制字符串转16进制数组
PNG("89504E47"),
/** GIF */
GIF("47494638"),
/** TIFF */
TIFF("49492A00"),
/** Windows bitmap */
BMP("424D"),
/** CAD */
DWG("41433130"),
/
** Adobe photoshop */
PSD("38425053"),
/** Rich Text Format */
RTF("7B5C727466"),
/** XML */
XML("3C3F786D6C"),
/** HTML */
HTML("68746D6C3E"),
/** Outlook Express */
DBX("CFAD12FEC5FD746F "),
/** Outlook */
PST("2142444E"),
/** doc;xls;dot;ppt;xla;ppa;pps;pot;msi;sdw;db */
OLE2("0xD0CF11E0A1B11AE1"),
/** Microsoft Word/Excel */
XLS_DOC("D0CF11E0"),
/** Microsoft Access */
MDB("5374616E64617264204A"),
/** Word Perfect */
WPB("FF575043"),
/** Postscript */
EPS_PS("252150532D41646F6265"),
/
** Adobe Acrobat */
PDF("255044462D312E"),
/** Windows Password */
PWL("E3828596"),
/** ZIP Archive */
ZIP("504B0304"),
/** ARAR Archive */
RAR("52617221"),
/** WAVE */
WAV("57415645"),
/** AVI */
AVI("41564920"),
/** Real Audio */
RAM("2E7261FD"),
/** Real Media */
RM("2E524D46"),
/** Quicktime */
MOV("6D6F6F76"),
/** Windows Media */
ASF("3026B2758E66CF11"),
/** MIDI */
MID("4D546864");
private String value = "";
private FileType(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
2.新建⼀个⽂件⼯具类,⽤来判断上传⽂件的类型
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class FilUtil {
/** 判断⽂件类型  */
public static FileType getType(String filePath) throws IOException {
// 获取⽂件头
String fileHead = getFileHeader(filePath);
if (fileHead != null && fileHead.length() > 0) {
fileHead = UpperCase();
FileType[] fileTypes = FileType.values();
for (FileType type : fileTypes) {
if (fileHead.Value())) {
return type;
}
}
}
return null;
}
/** 读取⽂件头 */
private static String getFileHeader(String filePath) throws IOException { byte[] b = new byte[28];
InputStream inputStream = null;
try {
inputStream = new FileInputStream(filePath);
} finally {
if (inputStream != null) {
inputStream.close();
}
}
return bytesToHex(b);
}
/
** 将字节数组转换成16进制字符串 */
public static String bytesToHex(byte[] src){
StringBuilder stringBuilder = new StringBuilder("");
if (src == null || src.length <= 0) {
return null;
}
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = HexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
String();
}
}
以上,需要注意的是,可能存在⼀种类型⽂件的魔数与另⼀种类型⽂件魔数的前⾯部分相等(如‘D0CF11E0’与‘D0CF11E0A1B11AE1’),所以应该尽量将更长的魔数值放在上⾯。这⾥的⽂件与魔数枚举得也不全⾯,但思路就这样吧。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。