Java 通过魔数判断上传文件的类型
程序员文章站
2024-02-19 18:49:40
...
前言
文件上传功能是很多网站都必须的功能,而判断文件类型不仅可以过滤文件的上传,同时也能防范用户上传恶意的可执行文件和脚本,以及将文件上传服务器当作免费的文件存储服务器使用。
而对于上传文件来说,不能简单的通过后缀名来判断文件的类型,因为恶意攻击可以将可执行文件的后缀名称改为图片或者其他格式,诱导用户执行,因此,判断上传文件的类型需要更安全的方式。
与Java的class文件类似,很多类型的文件,起始的几个字节内容都是固定的,跟据这几个字节的内容,就可以判断文件的类型,这几个字节也被称为“魔数”,比如class文件的魔数就是“CAFEBABE”。
通过魔数判断文件类型便是一种更安全的方式,其示例源码如下。
源码
1.新建一个文件类型的枚举类
public enum FileType {
/** JPEG */
JPEG("FFD8FF"),
/** PNG */
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 = fileHead.toUpperCase();
FileType[] fileTypes = FileType.values();
for (FileType type : fileTypes) {
if (fileHead.startsWith(type.getValue())) {
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);
inputStream.read(b, 0, 28);
} 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 = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
}
}