<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-67  評論-522  文章-0  trackbacks-0
        大象根據研究與實際項目經驗,向大家介紹一個關于文件類型驗證的解決辦法。不清楚的朋友可以了解下,知道的不喜勿噴。
        對于文件上傳,相信大家都不會陌生,我們都知道,文件在上傳到服務器的過程中,都是以流的形式傳輸的,在后臺處理文件上傳的代碼中,獲得這個流,然后讀取數據流將之保存到上傳文件的臨時目錄中,如果有使用到MongoDB,再將這個文件存儲到文件系統中。
        大部分的文件上傳都是通過HTML的上傳組件完成的,而業務需求往往是有類型要求的,比如只允許上傳jpggif、png類型的圖片,或者是只允許上傳Office文檔等等,雖然可以用JavaScript對上傳文件做一些類型驗證之類的控制,但還是不能完全做到過慮。這時,就需要在后臺,用代碼來進一步完成這個驗證工作。
        到底通過什么方式可以做到正確驗證呢?答案就是通過文件的頭部信息,通過大量測試,大象發現每種類型的文件,他們最開始的一段信息都是一樣的,比如Office97~03,它的頭四位16進制信息就是d0 cf 11 e0,而Office2007則是50 4b 03 04,PDF25 50 44 46,大家可以多用這樣的文件分別測試一下,看看前四位16進制信息是不是都是一樣的。當然這其中也有個別情況,比如jpg類型的圖片,它的前四位16進制信息就有兩種一個是ff d8 ff e0,另一個是ff d8 ff e1,區別是最后一位。知道了這些,我們就有一個方向了。
        可能有同學有疑問了,為什么只取前四位,不是六位或八位呢?這是因為,大象根據反復測試發現,從第五位開始到第八位,同一種類型的文件,在這幾位里面很有一些存在區別,像圖片以及pdf,這種現象很多,為了避免同一類型的文件,因為這一些小的不同,要定義N多檢測頭信息,這樣做似乎沒有必要,因此大象才建議取前四位作為類型檢測的依據。
        不過說了這么多,還是沒講怎么做,這顯然不是大象的風格,大象一般都從實際出發,用代碼來說話。

    package com.bolo.util;

    public class FileValidateUtil {

        public static boolean validateType(byte[] b, String customTypes) {

           if (b != null) {

               int size = b.length;

               String hex = null;

               StringBuilder contentType = new StringBuilder();

               for (int i = 0; i < size; i++) {

                  hex = Integer.toHexString(b[i] & 0xFF);

                  if (hex.length() == 1) {

                      hex = "0" + hex;

                  }

                  contentType.append(hex);

                  if (i > 2)

                      break;

               }

               if (customTypes.indexOf(contentType.toString()) > -1) {

                  return Boolean.TRUE;

               }

           }

           return Boolean.FALSE;

        }

    }
        上面這段代碼就是用來對文件類型作驗證的方法,第一個參數是文件的字節數組,第二個就是定義的可通過類型。代碼很簡單,主要是注意中間的一處,將字節數組的前四位轉換成16進制字符串,并且轉換的時候,要先和0xFF做一次與運算。這是因為,整個文件流的字節數組中,有很多是負數,進行了與運算后,可以將前面的符號位都去掉,這樣轉換成的16進制字符串最多保留兩位,如果是正數又小于10,那么轉換后只有一位,需要在前面補0,這樣做的目的是方便比較,取完前四位這個循環就可以終止了。
        下面我們準備些文件來測試一下這段代碼有沒有問題。

    package com.bolo.util;

    import java.io.IOException;

    import junit.framework.Assert;

    import org.apache.commons.io.FileUtils;

    import org.junit.Test;

    import org.springframework.util.ResourceUtils;

    import com.bolo.util.FileValidateUtil;

    public class FileValidateUtilTest {

        /**

         * 文件頭部信息,十六進制信息,取前4

         * 50 4b 03 04 office 2007+

         * d0 cf 11 e0 office 97~03

         * 25 50 44 46 pdf

         * ff d8 ff e0 jpg,部分pngjpg頭文件前4位一樣

         * ff d8 ff e1 jpg,一種不同的jpg頭文件

         * 89 50 4e 47 png

         */

        private static final String FILE_TYPE = "504b0304 d0cf11e0 25504446 ffd8ffe0 ffd8ffe1 89504e47";

        @Test

        public void jpgTest(){

            validateType("file/1.jpg");

        }

        @Test

        public void docTest(){

           validateType("file/2.doc");

        }

        @Test

        public void docxTest(){

            validateType("file/3.docx");

        }

        @Test

        public void pdfTest(){

            validateType("file/4.pdf");

        }

        @Test

        public void exeTest(){

            validateType("file/5.png");

        }

        private void validateType(String path){

            try {

                Assert.assertTrue(FileValidateUtil.validateType(FileUtils

                   .readFileToByteArray(ResourceUtils.getFile("classpath:" + path)), FILE_TYPE));

            } catch (IOException e) {

                e.printStackTrace();

            }

        }

    }
        從測試代碼可以看到文件類型,只有第五個不是正確文件,是我將一個exe文件通過改后綴為png。這個測試類,用到了commons-ioFileUtils,需要在pom中加入這個依賴,而ResourceUtilsorg.springframework.util包中,它屬于spring-core.jar,大象這個測試類是放在之前ssm3工程test里面,要想正常運行測試,要在test/resources目錄下建個file文件夾存放測試文件,最后編譯之后file及其測試文件都會在test-classes下面,所以文件查找是以classpath:開頭。
         OK,運行測試,結果就是前四個成功,最后一個失敗,這達到了我們的預期,只允許FILE_TYPE里面定義的文件類型通過測試。大家可以自己動手試驗一下。
        本文為菠蘿大象原創,如要轉載請注明出處。http://bolo.blogjava.net/ 
    posted on 2012-05-01 11:37 菠蘿大象 閱讀(6352) 評論(0)  編輯  收藏 所屬分類: Java
    主站蜘蛛池模板: 亚洲日韩中文在线精品第一| 四虎影视大全免费入口| 国产公开免费人成视频 | 久久亚洲sm情趣捆绑调教| 成人免费观看男女羞羞视频| 国产日本一线在线观看免费| 亚洲午夜精品久久久久久人妖| 成人一级免费视频| 亚洲人成网站色在线入口| AV激情亚洲男人的天堂国语| 成人免费网站在线观看| 亚洲av无码不卡久久| 91九色老熟女免费资源站| 亚洲国产日韩一区高清在线| 91精品国产免费久久国语蜜臀| 亚洲A∨无码一区二区三区| 久99久精品免费视频热77| 亚洲av无码一区二区三区网站| 久久精品乱子伦免费| 亚洲网站在线免费观看| 欧美在线看片A免费观看| 亚洲国产欧美一区二区三区| 女人18毛片免费观看| 国产精品亚洲一区二区在线观看| 亚洲精品宾馆在线精品酒店| 59pao成国产成视频永久免费 | 亚洲精品宾馆在线精品酒店 | 亚洲成a人片在线播放| 在线观看免费无码视频| 久久久无码精品亚洲日韩按摩| 毛片基地免费视频a| 无遮挡国产高潮视频免费观看| 精品亚洲综合在线第一区| 亚洲视频在线免费播放| 污污免费在线观看| 午夜亚洲国产理论秋霞| 国产精品国产免费无码专区不卡| 久久最新免费视频| 亚洲精品中文字幕| 亚洲AV午夜成人影院老师机影院 | 久久久久亚洲AV无码永不|