通过判断魔数来判断文件类型

import org.apache.commons.lang3.StringUtils;
 
/**
 * 文件类型与对应的文件魔数枚举类 
 *
 */
public enum FileTypeEnum { 
    
    /** JPEG  (jpg)*/
    JPEG("JPG", "FFD8FF"),
 
    /** PNG */
    PNG("PNG", "89504E47"),
 
    /** GIF */
    GIF("GIF", "47494638"),
  
    /** TIFF (tif)  */
    TIFF("TIF", "49492A00"),
 
    /** Windows bitmap (bmp) */
    BMP("BMP","424D"),
    
    BMP_16("BMP","424D228C010000000000"), //16色位图(bmp) 
    
    BMP_24("BMP","424D8240090000000000"), //24位位图(bmp)  
    
    BMP_256("BMP","424D8E1B030000000000"), //256色位图(bmp)     
 
    /** CAD  (dwg) */
    DWG("DWG", "41433130"),
 
    /** Adobe photoshop  (psd)*/
    PSD("PSD", "38425053"),
 
    /** Rich Text Format  (rtf)*/
    RTF("RTF", "7B5C727466"),
 
    /** XML */
    XML("XML", "3C3F786D6C"),
 
    /** HTML (html)*/
    HTML("HTML", "68746D6C3E"),
    
    /** Email [thorough only] (eml)*/
    EML("EML", "44656C69766572792D646174653A"),  
    
    /** Outlook Express (dbx) */
    DBX("DBX", "CFAD12FEC5FD746F "),
 
    /** Outlook (pst)*/
    PST("", "2142444E"),
 
    /** doc;xls;dot;ppt;xla;ppa;pps;pot;msi;sdw;db */
    OLE2("OLE2", "0xD0CF11E0A1B11AE1"),
 
    /** Microsoft Word/Excel 注意:word 和 excel的文件头一样 */
    XLS("XLS", "D0CF11E0"),
    
    /** Microsoft Word/Excel 注意:word 和 excel的文件头一样 */
    DOC("DOC", "D0CF11E0"),
    
    /** Microsoft Word/Excel 2007以上版本文件 注意:word 和 excel的文件头一样 */
    DOCX("DOCX", "504B0304"),  
 
    /** Microsoft Word/Excel 2007以上版本文件 注意:word 和 excel的文件头一样 504B030414000600080000002100*/
    XLSX("XLSX", "504B0304"), 
 
    /** Microsoft Access (mdb)*/
    MDB("MDB", "5374616E64617264204A"),
 
    /** Word Perfect (wpd)*/
    WPB("WPB", "FF575043"),
 
    /** Postscript */
    EPS("EPS", "252150532D41646F6265"),
 
    /** Postscript */
    PS("PS", "252150532D41646F6265"),
 
    /** Adobe Acrobat (pdf)  */
    PDF("PDF", "255044462D312E"),
    
    /** Quicken (qdf) */
    QDF("qdf", "AC9EBD8F"),
    
    /** QuickBooks Backup (qdb) */
    QDB("qbb", "458600000600"),
    
    /** Windows Password  (pwl)*/
    PWL("PWL", "E3828596"),
 
    /** ZIP Archive */
    ZIP("", "504B0304"),
 
    /** ARAR Archive */
    RAR("", "52617221"),
 
    /** WAVE (wav) */
    WAV("WAV", "57415645"),
 
    /** AVI */
    AVI("AVI", "41564920"),
 
    /** Real Audio (ram)*/
    RAM("RAM", "2E7261FD"),
 
    /** Real Media (rm) rmvb/rm相同  */
    RM("RM", "2E524D46"),
    
    /** Real Media (rm) rmvb/rm相同  */
    RMVB("RMVB", "2E524D46000000120001"),  
    
    /** MPEG (mpg)  */
    MPG("MPG", "000001BA"),
    
    /** Quicktime  (mov)*/
    MOV("MOV", "6D6F6F76"),
 
    /** Windows Media (asf) */
    ASF("ASF", "3026B2758E66CF11"),
 
    /** ARJ Archive */
    ARJ("ARJ", "60EA"),
 
    /** MIDI (mid) */
    MID("MID", "4D546864"),
    
    /** MP4 */  
    MP4("MP4", "00000020667479706D70"), 
    
    /** MP3 */  
    MP3("MP3", "49443303000000002176"),  
    
    /** FLV */  
    FLV("FLV", "464C5601050000000900"), 
    
    /** 1F8B0800000000000000 */
    GZ("GZ", "1F8B08"),
    
    /** CSS */ 
    CSS("CSS", "48544D4C207B0D0A0942"),
    
    /**  JS */  
    JS("JS", "696B2E71623D696B2E71"), 
     
    /**  Visio */  
    VSD("VSD", "d0cf11e0a1b11ae10000"),
    
    /** WPS文字wps、表格et、演示dps都是一样的 */  
    WPS("WPS", "d0cf11e0a1b11ae10000"),
    
    /** torrent */  
    TORRENT("TORRENT", "6431303A637265617465"), 
    
    /** JSP Archive */  
    JSP("JSP", "3C2540207061676520"),  
    
    /** JAVA Archive */  
    JAVA("JAVA", "7061636B61676520"), 
    
    /** CLASS Archive */  
    CLASS("CLASS", "CAFEBABE0000002E00"), 
    
    /** JAR Archive */  
    JAR("JAR", "504B03040A000000"), 
    
    /** MF Archive */  
    MF("MF", "4D616E69666573742D56"),
 
    /** EXE Archive */  
    EXE("EXE", "4D5A9000030000000400"), 
 
    /** ELF Executable */  
    ELF("ELF", "7F454C4601010100"), 
 
    /** Lotus 123 v1 */  
    WK1("WK1", "2000604060"),
    
    /** Lotus 123 v3 */  
    WK3("WK3", "00001A0000100400"),
    
    /** Lotus 123 v5 */  
    WK4("WK4", "00001A0002100400"), 
 
    /** Lotus WordPro v9 */  
    LWP("LWP", "576F726450726F"), 
    
    /** Sage(sly.or.srt.or.slt;sly;srt;slt) */  
    SLY("SLY", "53520100"), 
    
    /** CHM Archive */  
   /* CHM("CHM", "49545346030000006000"),  
    INI("INI", "235468697320636F6E66"), 
    SQL("SQL", "494E5345525420494E54"), 
    BAT("BAT", "406563686F206f66660D"),  
    PROPERTIES("", "6C6F67346A2E726F6F74"), 
    MXP("", "04000000010000001300"),  */
    
    NOT_EXITS_ENUM("", "");
    
    //文件类型对应的名称
    private String fileTypeName;
    
    //文件类型对应的魔数
    private String magicNumberCode;
    
    private FileTypeEnum(String fileTypeName, String magicNumberCode) {
        this.fileTypeName = fileTypeName;
        this.magicNumberCode = magicNumberCode;
    } 
     
    public String getFileTypeName() {
        return fileTypeName;
    } 
 
    public String getMagicNumberCode() {
        return magicNumberCode;
    }
 
 
    /**
     * 根据文件类型获取文件类型魔数编码
     * 默认返回标准件
     * @param magicNumberCode - 文件类型魔数编码
     * @return
     */
    public static FileTypeEnum getByMagicNumberCode(String magicNumberCode) {
        if (StringUtils.isNotBlank(magicNumberCode)) {
            for (FileTypeEnum type : values()) { 
                if (magicNumberCode.toUpperCase().startsWith(type.getMagicNumberCode())) {
                    return type; 
                } 
            } 
        }
        
        return FileTypeEnum.NOT_EXITS_ENUM;
    }
    
    /**
     * 根据文件类型后缀名获取枚举
     * 
     * @param fileTypeName - 文件类型后缀名
     * @return
     */
    public static FileTypeEnum getByFileTypeName(String fileTypeName) { 
        if (StringUtils.isNotBlank(fileTypeName)) {
            for (FileTypeEnum type : values()) {
                if (type.getFileTypeName().equals(fileTypeName)) {
                    return type; 
                } 
            }
        }
        return FileTypeEnum.NOT_EXITS_ENUM;
    }
  
}
  
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
 
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
 
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
  
/**
 * 通过文件魔数来判断文件类型
 * 可以最大量避免通过后缀名来判断文件类型的漏洞
 * 
 * @author 000125
 *
 */
public class FileTypeUtils {   
    private static final Logger LOGGER = LoggerFactory.getLogger(FileTypeUtils.class);
    
    /**  
     * 获取图片文件实际类型,若不是图片则返回null]
     * @param file 
     * @return fileType  
     */  
    public final static String getImageFileType(File file) {  
        if (isImage(file)) {
            try {
                ImageInputStream iis = ImageIO.createImageInputStream(file);
                Iterator<ImageReader> iter = ImageIO.getImageReaders(iis);
                if (!iter.hasNext()) {
                    return null;
                }
                ImageReader reader = iter.next();
                iis.close();
                return reader.getFormatName();
            } catch (IOException e) {
                return null;
            } catch (Exception e) {
                return null;
            }
        }
        return null;
    }  
  
    /**   
     * 获取文件类型,包括图片,若格式不是已配置的,则返回null
     * @param file 
     * @return fileType  
     */  
    public final static String getFileByFile(File file) {  
        String filetype = null;  
        byte[] b = new byte[50];  
        try {  
            InputStream is = new FileInputStream(file);  
            is.read(b);  
            filetype = getFileTypeByStream(b);  
            is.close();  
        } catch (FileNotFoundException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
        return filetype;  
    }  
      
    /** 
     * 通过数据流(二进制数据)判断文件类型
     * @param b 
     * @return fileType  
     */  
    public final static String getFileTypeByStream(byte[] b) {  
        String magicNumberCode = String.valueOf(getFileHexString(b));  
        
        if (StringUtils.isBlank(magicNumberCode)) { 
            return FileTypeEnum.getByMagicNumberCode(magicNumberCode.toUpperCase()).getFileTypeName();
            
        }
        return FileTypeEnum.NOT_EXITS_ENUM.getFileTypeName();  
    }  
      
    /** 
     * isImage,判断文件是否为图片
     * @param file
     * @return true 是 | false 否 
     */
    public static final boolean isImage(File file){
        boolean flag = false;
        try {
            BufferedImage bufreader = ImageIO.read(file);
            int width = bufreader.getWidth();
            int height = bufreader.getHeight();
            if(width==0 || height==0){
                flag = false;
            }else {
                flag = true;
            }
        } catch (IOException e) {
            flag = false;
        }catch (Exception e) {
            flag = false;
        }
        return flag;
    }
    
   
    /**
     * 通过文件路径判断文件类型
     * @param path
     * @return
     * @throws IOException
     */
    public static FileTypeEnum getFileTypeByPath(String path) {
        // 获取文件头
        String magicNumberCode = null;
        try {
            magicNumberCode = getFileHeader(path);
        } catch (Exception e) { 
            e.printStackTrace();
            return FileTypeEnum.NOT_EXITS_ENUM;
        }
 
        if (StringUtils.isBlank(magicNumberCode)) { 
            return FileTypeEnum.getByMagicNumberCode(magicNumberCode.toUpperCase());
            
        }
 
        return FileTypeEnum.NOT_EXITS_ENUM;
    }
 
    
    /**
     * 通过文件路径获取文件头(即文件魔数)
     * @param path
     * @return
     * @throws IOException
     */
    public static String getFileHeader(String path) throws Exception {
        byte[] b = new byte[28];
        InputStream inputStream = null;
 
        try {
            inputStream = new FileInputStream(path);
            inputStream.read(b, 0, 28);
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
        }
 
        return getFileHexString(b);
    }
    
    /**   
     * 把文件二进制流转换成十六进制数据
     * @param b 
     * @return fileTypeHex  
     */  
    public final static String getFileHexString(byte[] b) {  
        StringBuilder builder = new StringBuilder();  
        if (b == null || b.length <= 0) {  
            return null;  
        }  
        
        for (int i = 0; i < b.length; i++) {  
            int v = b[i] & 0xFF;  
            String hv = Integer.toHexString(v);  
            if (hv.length() < 2) {  
                builder.append(0);  
            }  
            builder.append(hv);  
        }  
        return builder.toString();  
    }  
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,635评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,628评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,971评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,986评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,006评论 6 394
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,784评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,475评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,364评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,860评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,008评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,152评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,829评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,490评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,035评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,156评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,428评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,127评论 2 356