Java上傳文件格式判斷


判斷用戶上傳文件的合法性僅僅通過后綴名是完全不夠的,誰也不知道后綴名是否被更改,服務器保存一個不知道真實類型的文件有極大的風險。

 

因此需要后台進行進一步的文件類型校驗,這里有兩種情況:

  1)一般的文件類型例如:jpg、png、xlsx等等是有固定文件頭的,提取出用戶上傳文件的文件頭與固定文件頭進行對比,就可以得到文件的准確類型。

  2)文本文件:txt、csv等等。文本文件具有特殊性,文本頭無明顯標志。但是文本文件百分百具有業務特殊性。可以在對文本進行格式驗證時,判斷是否為目標類型;或者通過編碼校驗,看文本是否正確編碼,是否有亂碼存在(正確編輯的文件,不可能存在亂碼),有第三方插件cpdetector可以檢測當前文件的編碼;最后還可以通過提供文件模板,固定文本文件的頭尾等方式來進行校驗。

 

這里主要說明第一種情況,第二種文本情況根據業務具體環境不同,有不同的處理方式。

文件類型枚舉👇

package com.uti.utilEnum;


public enum  FileTypeEnum {
    JPG("ffd8ffe000104a464946"),
    PNG("89504e470d0a1a0a0000"),
    GIF("47494638396126026f01"),
    TIF("49492a00227105008037"),
    BMP_1("424d228c010000000000"),//16色位圖(bmp)
    BMP_2("424d8240090000000000"),//24位位圖(bmp)
    BMP_3("424d8e1b030000000000"),//256色位圖(bmp)
    DWG("41433130313500000000"),
    HTML("3c21444f435459504520"),
    HTM("3c21646f637479706520"),
    CSS("48544d4c207b0d0a0942"),
    JS("696b2e71623d696b2e71"),
    RTF("7b5c727466315c616e73"),
    PSD("38425053000100000000"),
    EML("46726f6d3a203d3f6762"),
    DOC("d0cf11e0a1b11ae10000"),
    VSD("d0cf11e0a1b11ae10000"),
    MDB("5374616E64617264204A"),
    PS("252150532D41646F6265"),
    PDF("255044462d312e350d0a"),
    RMVB("2e524d46000000120001"),
    RM("2e524d46000000120001"),
    FLV("464c5601050000000900"),
    F4V("464c5601050000000900"),
    MP4("00000020667479706d70"),
    MP3("49443303000000002176"),
    MPG("000001ba210001000180"),
    WMV("3026b2758e66cf11a6d9"),
    ASF("3026b2758e66cf11a6d9"),
    WAV("52494646e27807005741"),
    AVI("52494646d07d60074156"),
    MID("4d546864000000060001"),
    ZIP("504b0304140000000800"),
    RAR("526172211a0700cf9073"),
    INI("235468697320636f6e66"),
    JAR("504b03040a0000000000"),
    EXE("4d5a9000030000000400"),
    JSP("3c25402070616765206c"),
    MF("4d616e69666573742d56"),
    XML("3c3f786d6c2076657273"),
    SQL("494e5345525420494e54"),
    JAVA("7061636b616765207765"),
    BAT("406563686f206f66660d"),
    GZ("1f8b0800000000000000"),
    PROPERTIES("6c6f67346a2e726f6f74"),
    CLASS("cafebabe0000002e0041"),
    CHM("49545346030000006000"),
    MXP("04000000010000001300"),
    DOCX("504b0304140006000800"),
    WPS("d0cf11e0a1b11ae10000"),
    TORRENT("6431303a637265617465"),
    MOV("6D6F6F76"),
    WPD("FF575043"),
    DBX("CFAD12FEC5FD746F"),
    PST("2142444E"),
    QDF("AC9EBD8F"),
    PWL("E3828596"),
    RAM("2E7261FD");

    private String value = "";

    private FileTypeEnum(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

具體代碼👇

    private boolean notTextFileTypeCheck(InputStream inputStream, String specifiedType) throws IOException {
        boolean fileTypeIsVaild = false;
        byte[] buffer = new byte[10];
        inputStream.read(buffer);

        //獲取當前文件的真實類型
        String curfileType = getTrueFileType(bytesToHexFileTypeString(buffer));

        //指定文件類型中是否匹配當前文件類型
        if(specifiedType.toUpperCase().equals(curfileType)){
            fileTypeIsVaild = true;
        }
        return fileTypeIsVaild;
    }

    private String getTrueFileType(String s) {
        for (FileTypeEnum fileTypeEnum : FileTypeEnum.values()) {
            if (s.startsWith(fileTypeEnum.getValue())) {
                return fileTypeEnum.toString();
            }
        }
        return null;
    }

    private String bytesToHexFileTypeString(byte[] buffer) {
        StringBuilder hexFileTypeStr = new StringBuilder();
        for (byte b : buffer) {
            String hexString = Integer.toHexString(b & 0xFF);
            if (hexString.length() < 2) {
                hexFileTypeStr.append("0");
            }
            hexFileTypeStr.append(hexString);
        }
        return hexFileTypeStr.toString();
    }
關於為什么要&0xFF,推薦一篇文章https://www.cnblogs.com/think-in-java/p/5527389.html,加上評論更好理解,還能回顧下“原碼反碼補碼”的知識


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM