Java 对上传文件进行魔数校验

魔数这个词在不同领域代表不同的含义。在计算机领域,魔数有两个含义,一指用来判断文件类型的魔数(magic number);二指程序代码中的魔数,也称魔法值。

不是所有文件都有文件头的。一个.txt类型的文件是一个纯文本文件,没有文件头。

参考文章:

百科 魔数

Java 通过魔数判断上传文件的类型

 

项目中接到魔数校验的需求,这篇文章(Java 通过魔数判断上传文件的类型)对我理解很有帮助,在此基础上,我重新写了工具类的处理,通过文件路径或者文件流获取文件类型(文件类型与对应的文件魔数枚举类),然后通过 FileTypeEnum枚举类的数据再去根据需求处理不同的文件业务。

1、 新建 FileTypeEnum类:文件类型与对应的文件魔数枚举类

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;
    }

}

2、新建 FileTypeUtil工具类 测试

import cn.jq.javademo.utils.pojo.FileTypeEnum;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * 文件类型与对应的文件魔数处理工具类
 */
public class FileTypeUtil {

    public static void main(String[] args) throws Exception {
        File fromPic = new File("D:\\E\\电脑壁纸\\JD导入.xlsx");

        FileTypeEnum fileTypeEnum = FileTypeUtil.getFileTypeByInputStream(new FileInputStream(fromPic));
        System.out.println(fileTypeEnum.getFileTypeName());
        System.out.println(fileTypeEnum.getMagicNumberCode());
        System.out.println(fileTypeEnum);

        FileTypeEnum fileTypeEnum2 = FileTypeUtil.getFileTypeByPath("D:\\E\\电脑壁纸\\598a80e12f9ad.jpg");
        System.out.println(fileTypeEnum2.getFileTypeName());
        System.out.println(fileTypeEnum2.getMagicNumberCode());
        System.out.println(fileTypeEnum2);
    }


    /**
     * 通过文件路径获取文件类型
     * @param path
     * @return FileTypeEnum - 文件类型与对应的文件魔数枚举类
     */
    public static FileTypeEnum getFileTypeByPath(String path) {
        // 获取文件头
        String magicNumberCode = magicNumberCode = getFileHeaderHexByPath(path);
        if (StringUtils.isNotBlank(magicNumberCode)) {
            return FileTypeEnum.getByMagicNumberCode(magicNumberCode.toUpperCase());
        }
        return FileTypeEnum.NOT_EXITS_ENUM;
    }

    /**
     * 通过文件流获取文件类型
     * @param inputStream
     * @return FileTypeEnum - 文件类型与对应的文件魔数枚举类
     */
    public static FileTypeEnum getFileTypeByInputStream(InputStream inputStream) {
        // 获取文件头
        String magicNumberCode = getFileHeaderHexByInputStream(inputStream);
        if (StringUtils.isNotBlank(magicNumberCode)) {
            return FileTypeEnum.getByMagicNumberCode(magicNumberCode.toUpperCase());
        }
        return FileTypeEnum.NOT_EXITS_ENUM;
    }


    /**
     * 获取文件头(即文件魔数),根据文件路径
     * @param path
     * @return fileHeaderHex - 文件头,即文件魔数
     */
    public static String getFileHeaderHexByPath(String path){
        byte[] b = new byte[28];
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(path);
            inputStream.read(b, 0, 28);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return bytesToHexString(b);
    }

    /**
     * 获取文件头(即文件魔数),根据通过文件流
     * @param inputStream
     * @return fileHeaderHex - 文件头,即文件魔数
     */
    public static String getFileHeaderHexByInputStream(InputStream inputStream) {
        byte[] b = new byte[28];
        try {
            inputStream.read(b, 0, 28);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return bytesToHexString(b);
    }

    /**
     * 将文件二进制流(即字节数组)转换成16进制字符串数据
     * @param b
     * @return fileHeaderHex - 文件头,即文件魔数
     */
    private final static String bytesToHexString(byte[] b) {
        StringBuilder stringBuilder = 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) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }
}

     

 

—— Stay Hungry. Stay Foolish. 求知若饥,虚心若愚。

  • 4
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值