首页 > 代码库 > 读取16进制文件和校验图片格式的问题。 文件名后缀

读取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

 

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