當(dāng)我們開發(fā)的時(shí)候,經(jīng)常會(huì)有上下傳文件的需求。這就難免會(huì)遇到獲取文件類型的情況。如果根據(jù)文件名后綴,或者下載url后綴獲取,是不是有點(diǎn)low。而且還可能存在問題,比如我們可以輕易修改文件的后綴,而且下載鏈接很多都是加密過的是看不到文件后綴的。
那問題來(lái)了,文件類型是如何規(guī)定的。我下面來(lái)幾張圖就懂了
我們右鍵用文本編輯器打開pdf文件,然后我們會(huì)看到一堆16進(jìn)制字符

1.png
我們要清楚一個(gè)字節(jié)有8位,等于位數(shù)為2的16進(jìn)制。比如上圖紅款內(nèi)的
25 50 44 46 2d 31 2e,這就代表7個(gè)字節(jié)。然后我們將這7個(gè)字節(jié)轉(zhuǎn)換成ASCII會(huì)發(fā)現(xiàn)50對(duì)應(yīng)P,44對(duì)應(yīng)D,46對(duì)應(yīng)F即PDF??!然后你去嘗試其他格式的文件也會(huì)發(fā)現(xiàn)都是按這個(gè)規(guī)則,所以我們可以通過文件的16進(jìn)制編碼的前幾個(gè)字節(jié)判斷文件的類型。

2.png
每種文件的前幾個(gè)字節(jié)是固定的,它們被稱為魔數(shù),255044462d312e這串16進(jìn)制碼就是對(duì)應(yīng)文件的魔數(shù),每種文件類型只有一種魔數(shù)。下面是常見的魔數(shù),你們也可以用其他編碼當(dāng)作文件的魔數(shù)對(duì)應(yīng)
Adobe Acrobat (pdf),文件頭:255044462D312E
JPEG (jpg),文件頭:FFD8FF
PNG (png),文件頭:89504E47
GIF (gif),文件頭:47494638
TIFF (tif),文件頭:49492A00
Windows Bitmap (bmp),文件頭:424D
CAD (dwg),文件頭:41433130
Adobe Photoshop (psd),文件頭:38425053
Rich Text Format (rtf),文件頭:7B5C727466
XML (xml),文件頭:3C3F786D6C
HTML (html),文件頭:68746D6C3E
Email [thorough only] (eml),文件頭:44656C69766572792D646174653A
Outlook Express (dbx),文件頭:CFAD12FEC5FD746F
Outlook (pst),文件頭:2142444E
MS Word/Excel (xls.or.doc),文件頭:D0CF11E0
MS Access (mdb),文件頭:5374616E64617264204A
WordPerfect (wpd),文件頭:FF575043
Postscript (eps.or.ps),文件頭:252150532D41646F6265
Quicken (qdf),文件頭:AC9EBD8F
Windows Password (pwl),文件頭:E3828596
ZIP Archive (zip),文件頭:504B0304
RAR Archive (rar),文件頭:52617221
Wave (wav),文件頭:57415645
AVI (avi),文件頭:41564920
Real Audio (ram),文件頭:2E7261FD
Real Media (rm),文件頭:2E524D46
MPEG (mpg),文件頭:000001BA
MPEG (mpg),文件頭:000001B3
Quicktime (mov),文件頭:6D6F6F76
Windows Media (asf),文件頭:3026B2758E66CF11
MIDI (mid),文件頭:4D546864
所謂實(shí)干興邦,下面我用java語(yǔ)言實(shí)現(xiàn)。其它語(yǔ)言也是按上面的規(guī)則走是沒問題的。
public class FileTypeTest {
public static void main(String[] arg) {
try (InputStream inputStream = new FileInputStream("C:/Users/Administrator/Desktop/Java8函數(shù)式編程.pdf")){
//讀取10個(gè)字節(jié)
byte[] abc = new byte[10];
inputStream.read(abc);
//每個(gè)字節(jié)轉(zhuǎn)換成16進(jìn)制
StringBuffer sb = new StringBuffer();
for (byte item : abc){
if ((item&0xF0)==0) sb.append("0");
sb.append(Integer.toHexString(item&0xFF));
}
String hexStr = sb.toString().toUpperCase();
System.out.println(hexStr);
//通過枚舉找到對(duì)應(yīng)的類型
FileTypeEnumTest[] fileTypeEnums = FileTypeEnumTest.values();
for (FileTypeEnumTest item:fileTypeEnums){
if (hexStr.contains(item.getKey())){
System.out.println("匹配到文件類型:"+item.getFiletype());
}
}
}catch (Exception e){
e.printStackTrace();
}
}
enum FileTypeEnumTest{
PDF("255044462D312E",".pdf"),
JPEG("FFD8FF",".jpg");
FileTypeEnumTest(String key,String fileType){
this.key= key;
this.fileType= fileType;
}
public String getKey(){return key;}
public String getFiletype(){return fileType;}
private String key;
private String fileType;
}
}
這種方式其實(shí)也不能保證那些刻意修改文件字節(jié)的情況。
如有問題或更好的方法請(qǐng)聯(lián)系我,感謝 flower