利用文件头判断文件类型 利用文件头判断文件类型

时间:2024-02-23 11:12:40

上传文件时经常需要做文件类型判断,例如图片、文档等,普通做法是直接判断文件后缀名,而文艺青年为了防止各种攻击同时也会加上使用文件头信息判断文件类型。

原理很简单:用文件头判断,直接读取文件的前2个字节即可。

 1 public class FileUtil {
 2     /**
 3      * byte数组转换成16进制字符串
 4      * 
 5      * @param src
 6      * @return
 7      */
 8     private static String bytesToHexString(byte[] src) {
 9         StringBuilder stringBuilder = new StringBuilder();
10         if (src == null || src.length <= 0) {
11             return null;
12         }
13         for (int i = 0; i < src.length; i++) {            
14             // 以十六进制(基数 16)无符号整数形式返回一个整数参数的字符串表示形式,并转换为大写
15             String hv = Integer.toHexString(src[i] & 0xFF).toUpperCase();
16             if (hv.length() < 2) {
17                 stringBuilder.append(0);
18             }
19             stringBuilder.append(hv);
20         }
21         return stringBuilder.toString();
22     }
23     
24     /**
25      * 根据文件路径获取文件头信息
26      * 
27      * @param filePath
28      *            文件路径
29      * @return 文件头信息
30      */
31     public static String getFileType(String filePath) {
32         String bytes = getFileHeader(filePath);
33         if (bytes != null) {
34             if (bytes.contains("FFD8FF")) {
35                 return "jpg";
36             } else if (bytes.contains("89504E47")) {
37                 return "png";
38             } else if (bytes.contains("47494638")) {
39                 return "gif";
40             } else if (bytes.contains("49492A00")) {
41                 return "tif";
42             } else if (bytes.contains("424D")) {
43                 return "bmp";
44             }
45         }        
46         return null;
47     }
48 
49     
50     /**
51      * 根据文件路径获取文件头信息
52      * 
53      * @param filePath
54      *            文件路径
55      * @return 文件头信息
56      */
57     public static String getFileHeader(String filePath) {
58         FileInputStream is = null;
59         String value = null;
60         try {
61             is = new FileInputStream(filePath);
62             byte[] b = new byte[4];
63             is.read(b, 0, b.length);
64             value = bytesToHexString(b);
65         } catch (Exception e) {
66         } finally {
67             if (null != is) {
68                 try {
69                     is.close();
70                 } catch (IOException e) {
71                 }
72             }
73         }
74         return value;
75     }
76 
77     public static void main(String[] args) throws Exception {
78         System.out.println(getFileType("F:\\old file\\论坛头像数据采集\\未命名.bmp"));
79     }
80 }

这里增加客户端jsp调用实例

String ext = FileUtil.getFileType(srcFilePath);
if(app.getFileExts()!=null && !app.getFileExts().contains(ext)){
      File invalidFile = new File(srcFilePath);
      if(invalidFile.isFile()) invalidFile.delete();
      System.out.println("Unsupport file type: "+ext+" in tx:"+tx.getTransactionId());
      throw new Exception("Unsupport file type: "+ext+" in tx:"+tx.getTransactionId());
}

顺便贴上各种常见文件头

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  
Adobe Acrobat (pdf),文件头:255044462D312E  
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

 参考: