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

  • 相关阅读:
    Microsoft SQL Server 2008 基本安装说明
    微软的招聘哲学——做微软人的五大核心素质
    大型网站性能优化的通用方法
    模型驱动的开发,回忆一年多前的一次开发
    远离客户陷阱小故事 转
    单例模式(Singleton)
    真的很高兴,就在今天“博客园团队”为我们开通了 “CSLA 团队”
    桥接模式(Bridge)与合成/聚合复用原则(CARP)
    2009年11月11日
    虚拟化的好处 随笔
  • 原文地址:https://www.cnblogs.com/xxchao/p/3982031.html
Copyright © 2020-2023  润新知