當(dāng)我們開發(fā)的時(shí)候忱屑,經(jīng)常會有上下傳文件的需求。這就難免會遇到獲取文件類型的情況暇昂。如果根據(jù)文件名后綴莺戒,或者下載url后綴獲取,是不是有點(diǎn)low话浇。而且還可能存在問題脏毯,比如我們可以輕易修改文件的后綴,而且下載鏈接很多都是加密過的是看不到文件后綴的幔崖。
那問題來了食店,文件類型是如何規(guī)定的。我下面來幾張圖就懂了
我們右鍵用文本編輯器打開pdf文件赏寇,然后我們會看到一堆16進(jìn)制字符
我們要清楚一個(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會發(fā)現(xiàn)50對應(yīng)P自娩,44對應(yīng)D,46對應(yīng)F即PDFG恕忙迁!然后你去嘗試其他格式的文件也會發(fā)現(xiàn)都是按這個(gè)規(guī)則,所以我們可以通過文件的16進(jìn)制編碼的前幾個(gè)字節(jié)判斷文件的類型。
每種文件的前幾個(gè)字節(jié)是固定的碎乃,它們被稱為魔數(shù)姊扔,255044462d312e這串16進(jìn)制碼就是對應(yīng)文件的魔數(shù),每種文件類型只有一種魔數(shù)梅誓。下面是常見的魔數(shù)恰梢,你們也可以用其他編碼當(dāng)作文件的魔數(shù)對應(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語言實(shí)現(xiàn)杂伟。其它語言也是按上面的規(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);
//通過枚舉找到對應(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é)的情況仍翰。
如有問題或更好的方法請聯(lián)系我赫粥,感謝 flower