读取16进制文件和校验图片格式的问题。 文件名后缀

概要:

  前段时间,要做这样一个校验:当不符合要求的文件,通过修改文件后缀名后,仍然不允许上传。

我想这是大家经常会遇到的一个校验问题。我才用的办法是:用16进制读取文件头部(不妨成为head),比较head和常见文件头部16进制编码,进行判断。

我个人认为,这个校验方法有弊端,例如当两中不同的文件的文件头编码一样时,一种符合上传要求,一种不符合上传要求,起不到校验功能,例如office 2007和zip。

但是这个方法还是很实用的,毕竟文件头一样的不同文件总是不多的,而且在网站上传是碰到的就更少了,对图片校验还是非常有效的,目前没发现常见图片文件头相同的现象。

注明:office 2007和zip,一般都是允许的上传文件格式,“你可以上传ppt/pptx, doc/docx, ... ,多个文件可以压缩成zip,rar上传”,所以不用担心这个情况了。同文件头编码总是不多的!

ZIP Archive (zip),文件头:504B0304 
MS Word/Excel (xlsx pptx docx),文件头: 504B0304
当 docx 没有内容时,没有找到文件头;当它有内容时,它有文件头:504B0304

文章顺序:

1.常见文件后缀名

2.我的代码

3.参考的资料

1.常见文件后缀名

参见:http://www.cnblogs.com/xxchao/p/3965005.html

2.我的代码

 代码有什么改进的方法,求高手指教一二,谢谢。

。。。。
InputStream in = fileItem.getInputStream();
                    String head = readOriginal2Hex(in, 4).toUpperCase();
                    if(null == head || "".equals(head)){
                        msgBean.setMsg("请上传.jpg/.jpeg/.png/.gif/.bmp的格式").setMsgCode(MsgBean.MsgCode.FAILURE);
                        return msgBean;
                    }
                   /* 文件开头的标志字符
                    JPEG (jpg),文件头:FFD8FF 
                    PNG (png),文件头:89504E47 
                    GIF (gif),文件头:47494638
                    Windows Bitmap (bmp),文件头:424D 
                     */
    if("47494638".equals(head) || "89504E47".equals(head) || "FFD8FF".equals(head.substring(0, 6)) || "424D".equals(head.substring(0, 4))){

。。。。 //做你要的业务

}
                                        
。。。。。


/**
     * 读取文件开头n个字节,为16进制String
     * @param InputStream
     * @param int
     * @return String
     * @throws IOException
     */
    public String readOriginal2Hex(InputStream in, int n) throws IOException{
        //FileInputStream fin = new FileInputStream(new File(RO_HOME + BAK_FILE));
        StringWriter sw = new StringWriter();
        int len = 1;
        byte[] temp = new byte[len]; //字节,字节(Byte)是计算机信息技术用于计量存储容量和传输容量的一种计量单位,1个字节等于8位二进制。
        
        //16进制转化模块
        for(int i = 0; (in.read(temp, 0, len)!=-1) && (i < n); i++){
            if(temp[0] > 0xf && temp[0] <= 0xff){ // 10~ff
                sw.write(Integer.toHexString(temp[0]));
            }else if(temp[0] >= 0x0 && temp[0] <= 0xf){  // 0~f
                //对于只有一位的16进制数前面补“0”
                sw.write("0" + Integer.toHexString(temp[0]));                
            }else{
                //对于int<0的位转化为16进制的特殊处理,因为Java没有Unsigned int,所以这个int可能为负数
                sw.write(Integer.toHexString(temp[0]).substring(6));  
/* 对于为什么是从6开始截,这涉及内存溢出的知识,我的解释是:java调试跟踪查到 -1   ffffffff,-40  ffffffd8,-31  ffffffe1 ,一个字节8位二进制,最大255 = ff,
一个16进制数由4位二进制数转化得来,这里无符号数才能到达255,下次在说理由。。 有知道的说下。。
 
 */
            }
        }
        
        return sw.toString();
    }

3.参考的资料

http://blog.csdn.net/cdtdx/article/details/1529804

原文地址:https://www.cnblogs.com/xxchao/p/3982031.html