java根据“魔数”判断上传的文件类型

转载 2018年04月16日 21:32:35

与Java的class文件类似,很多类型的文件,起始的几个字节内容都是固定的,跟据这几个字节的内容,就可以判断文件的类型,这几个字节也被称为“魔数”,比如class文件的魔数就是“CAFEBABE”。

通过魔数判断文件类型便是一种更安全的方式:

一:创建枚举类

public enum FileType {

    /** JPEG */
    JPEG("FFD8FF"),

    /** PNG */
    PNG("89504E47"),

    /** GIF */
    GIF("47494638"),

    /** TIFF */
    TIFF("49492A00"),

    /** Windows bitmap */
    BMP("424D"),

    /** CAD */
    DWG("41433130"),

    /** Adobe photoshop */
    PSD("38425053"),

    /** Rich Text Format */
    RTF("7B5C727466"),

    /** XML */
    XML("3C3F786D6C"),

    /** HTML */
    HTML("68746D6C3E"),

    /** Outlook Express */
    DBX("CFAD12FEC5FD746F "),

    /** Outlook */
    PST("2142444E"),

    /** doc;xls;dot;ppt;xla;ppa;pps;pot;msi;sdw;db */
    OLE2("0xD0CF11E0A1B11AE1"),

    /** Microsoft Word/Excel */
    XLS_DOC("D0CF11E0"),

    /** Microsoft Access */
    MDB("5374616E64617264204A"),

    /** Word Perfect */
    WPB("FF575043"),

    /** Postscript */
    EPS_PS("252150532D41646F6265"),

    /** Adobe Acrobat */
    PDF("255044462D312E"),

    /** Windows Password */
    PWL("E3828596"),

    /** ZIP Archive */
    ZIP("504B0304"),

    /** ARAR Archive */
    RAR("52617221"),

    /** WAVE */
    WAV("57415645"),

    /** AVI */
    AVI("41564920"),

    /** Real Audio */
    RAM("2E7261FD"),

    /** Real Media */
    RM("2E524D46"),

    /** Quicktime */
    MOV("6D6F6F76"),

    /** Windows Media */
    ASF("3026B2758E66CF11"),

    /** MIDI */
    MID("4D546864");

    private String value = "";

    private FileType(String value) {
        this.value = value;
    }
    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }

}

二:创建工具类

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

public class FilUtil {


    /** 判断文件类型  */
    public static FileType getType(String filePath) throws IOException {
        // 获取文件头
        String fileHead = getFileHeader(filePath);
        if (fileHead != null && fileHead.length() > 0) {
            fileHead = fileHead.toUpperCase();
            FileType[] fileTypes = FileType.values();
            for (FileType type : fileTypes) {
                if (fileHead.startsWith(type.getValue())) {
                    return type;
                }
            }
        }
        return null;
    }

    /** 读取文件头 */
    private static String getFileHeader(String filePath) throws IOException {
        byte[] b = new byte[28];
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(filePath);
            inputStream.read(b, 0, 28);
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
        }
        return bytesToHex(b);
    }

    /** 将字节数组转换成16进制字符串 */
    public static String bytesToHex(byte[] src){  
        StringBuilder stringBuilder = new StringBuilder("");  
        if (src == null || src.length <= 0) {  
            return null;  
        }
        for (int i = 0; i < src.length; i++) {  
            int v = src[i] & 0xFF;  
            String hv = Integer.toHexString(v);  
            if (hv.length() < 2) {  
                stringBuilder.append(0);  
            }  
            stringBuilder.append(hv);  
        }  
        return stringBuilder.toString();  
    } 

}

需要注意的是,可能存在一种类型文件的魔数与另一种类型文件魔数的前面部分相等(如‘D0CF11E0’与‘D0CF11E0A1B11AE1’),所以应该尽量将更长的魔数值放在上面。这里的文件与魔数枚举得也不全面,但思路就这样。


以下例出的是一些我们常见的文件类型,以及它用于判断这种文件的类型的几个开始字节及所对尖的ASCII数字:

图片文件

文件类型 扩展名 16进制数字
xx这里表示变量
Ascii数字
. = 不是Ascii字符
Bitmap format .bmp 42 4d BM
FITS format .fits 53 49 4d 50 4c 45 SIMPLE
GIF format .gif 47 49 46 38 GIF8
Graphics Kernel System .gks 47 4b 53 4d GKSM
IRIS rgb format .rgb 01 da ..
ITC (CMU WM) format .itc f1 00 40 bb ….
JPEG File Interchange Format .jpg ff d8 ff e0 ….
NIFF (Navy TIFF) .nif 49 49 4e 31 IIN1
PM format .pm 56 49 45 57 VIEW
PNG format .png 89 50 4e 47 .PNG
Postscript format .[e]ps 25 21 %!
Sun Rasterfile .ras 59 a6 6a 95 Y.j.
Targa format .tga xx xx xx
TIFF format (Motorola – big endian) .tif 4d 4d 00 2a MM.*
TIFF format (Intel – little endian) .tif 49 49 2a 00 II*.
X11 Bitmap format .xbm xx xx  
XCF Gimp file structure .xcf 67 69 6d 70 20 78 63 66 20 76 gimp xcf
Xfig format .fig 23 46 49 47 #FIG
XPM format .xpm 2f 2a 20 58 50 4d 20 2a 2f /* XPM */

压缩文件

文件类型 扩展名 16进制数字
xx这里表示变量
Ascii数字
. = 不是Ascii字符
Bzip .bz 42 5a BZ
Compress .Z 1f 9d ..
gzip format .gz 1f 8b ..
pkzip format .zip 50 4b 03 04 PK..

存档文件

文件类型 扩展名 16进制数字
xx这里表示变量
Ascii数字
. = 不是Ascii字符
TAR (pre-POSIX) .tar xx xx (a filename)
TAR (POSIX) .tar 75 73 74 61 72 ustar (offset by 257 bytes)

可执行文件

文件类型 扩展名 16进制数字
xx这里表示变量
Ascii数字
. = 不是Ascii字符
MS-DOS, OS/2 or MS Windows   4d 5a MZ
Unix elf   7f 45 4c 46 .ELF

其它文件

文件类型 扩展名 16进制数字
xx这里表示变量
Ascii数字
. = 不是Ascii字符
pgp public ring   99 00 ..
pgp security ring   95 01 ..
pgp security ring   95 00 ..
pgp encrypted data   a6 00 ¦.

 除上述“魔数”外,还可以判断图片是否可以缩放,即获取长和宽:

/**   
     * <p>Discription:[isImage,判断文件是否为图片]</p>  
     * @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;  
    }  


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

前言文件上传功能是很多网站都必须的功能,而判断文件类型不仅可以过滤文件的上传,同时也能防范用户上传恶意的可执行文件和脚本,以及将文件上传服务器当作免费的文件存储服务器使用。而对于上传文件来说,不能简单...
  • t894690230
  • t894690230
  • 2016-04-25 14:36:39
  • 3347

各类文件的文件头 魔数

从网上找的 正确性有待验证... 1、从Ultra-edit-32中提取出来的 JPEG (jpg),文件头:FFD8FF  PNG (png),文件头:89504E47  ...
  • shendeguang
  • shendeguang
  • 2014-01-18 14:20:42
  • 2543

java根据“魔数”判断上传的文件类型

与Java的class文件类似,很多类型的文件,起始的几个字节内容都是固定的,跟据这几个字节的内容,就可以判断文件的类型,这几个字节也被称为“魔数”,比如class文件的魔数就是“CAFEBABE”。...
  • Bob__Zhang
  • Bob__Zhang
  • 2018-04-16 21:32:35
  • 11

Java判断文件类型

通常,在WEB系统中,上传文件时都需要做文件的类型校验,大致有如下几种方法: 1. 通过后缀名,如exe,jpg,bmp,rar,zip等等。 2. 通过读取文件,获取文件的Content-typ...
  • ryelqy
  • ryelqy
  • 2017-07-11 16:07:20
  • 425

Java 的 Class 文件格式——解析魔数和版本号

解析 Java 的 Class 文件格式——解析魔数和版本号 作者:陈跃峰 出自: http://blog.csdn.net/mailbomb           熟悉 Java 语言有好几年了,技术...
  • seeknow
  • seeknow
  • 2006-08-16 17:12:00
  • 1571

如何更好的判断系统上传文件是指定文件类型--文件魔术数字

这里所说的表示不同文件类型的魔术数字,指定是文件的最开头的几个用于唯一区别其它文件类型的字节,有了这些魔术数字,我们就可以很方便的区别不同的文件,这也使得编程变得更加容易,因为我减少了我们用于区别一个...
  • fengspg
  • fengspg
  • 2016-03-03 15:06:17
  • 699

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

这里所说的表示不同文件类型的魔术数字,指定是文件的最开头的几个用于唯一区别其它文件类型的字节,有了这些魔术数字,我们就可以很方便的区别不同的文件,这也使得编程变得更加容易,因为我减少了我们用于区别一个...
  • ycb1689
  • ycb1689
  • 2018-03-27 14:29:25
  • 31

魔数,常见魔数

java 文件编译为 .class 字节码(byte code),字节码文件的前 4 位为魔数(起到标识说明作用),magicNumber = 0xCAFEBABE; 1. 可执行文件 几乎所有...
  • lanchunhui
  • lanchunhui
  • 2017-12-16 22:37:04
  • 104

java上传文件以流方式判断类型

public enum FileType { /** * JEPG. */ JPEG("FFD8FF"), ...
  • winter13292
  • winter13292
  • 2013-09-03 15:24:12
  • 7344

解析Java的Class文件格式——解析魔数和版本号(一)

解析Java的Class文件格式——解析魔数和版本号(一)作者:陈跃峰出自:http://blog.csdn.net/mailbomb        熟悉Java语言有好几年了,技术也学了一些,现在主...
  • Mailbomb
  • Mailbomb
  • 2005-12-19 11:26:00
  • 6003
收藏助手
不良信息举报
您举报文章:java根据“魔数”判断上传的文件类型
举报原因:
原因补充:

(最多只允许输入30个字)