天天看點

java之檔案上傳二(源碼)

基礎知識在前面一篇,檔案上傳代碼。耐心看到後面的重構,簡潔多了

重構代碼下載下傳:http://download.csdn.net/detail/xiaozhegaa/9782629

(一) 開發思路:代碼看起來有點亂,但是是有思路的

1:工廠–>對象設計模式。建立工廠—–>設定一下工廠的屬性,其中涉及了臨時檔案,那麼在源碼第一二行先取得上傳的真實路徑和臨時路徑

2:得到對象,先設定上傳檔案的字元編碼問題,然後判斷是否是MIME協定送出

      > 3.1:若不是MIME協定送出,抛異常,提示說要用MIME送出,若不然就收集不到資料哦

      >> 3.2 : 若是MIME協定送出,則要把上傳的内容轉化成FileItemList。也就是用parseRequest()

4:取到list集合之後,循環周遊,判斷是否是普通字段

      >> 5:如果是普通字段的話,那麼采用一般的bean裝在就可以 //user.getUsername(“xxx”)

      > > 6:否則就檔案字段,那麼對檔案進行處理

7:這是擴充的功能:各種if

      >>7.1 :if(fileItem.endWith(“jpg”)) //上傳是jpg,給不給通過

      >>7.2 :if(fileItem.getSize()==0) //空檔案,給不給通過,還是抛異常

      > >7.3 :if(fileItem.gizeSize() > 1024 * 200) //檔案大于200k,給不給通過

      > >7.4 :………等等

8:然後就讀寫資料,is.readLine(),os.write()。java基礎固定寫法

9:删除臨時檔案

10:顯示上傳成功頁面

public class UploadServlet2 extends HttpServlet {
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //取得上傳的真實路徑和臨時路徑
        String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");
        String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
        //使用第一個類u
        //建立上傳檔案的工廠
        DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();
        //設定記憶體中的緩沖區大小。10k
        fileItemFactory.setSizeThreshold(*);
        //設定上傳檔案臨時存放的目錄
        fileItemFactory.setRepository(new File(tempPath));

        //使用第二個類
        //建立上傳檔案的對象
        ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
        //設定上傳檔案名字的字元編碼
        servletFileUpload.setHeaderEncoding("UTF-8");
        //判斷用戶端是否是采用那個了mime協定去上傳檔案
        boolean flag = servletFileUpload.isMultipartContent(request);
        if(!flag){
            //也就是不是采用mime的協定上傳檔案,那麼抛異常。這裡也可以采用一般的方式去處理哦哦
            throw new ServletException();
        }else{

            /*也就是說是采用了MIME的協定上傳檔案
             * 解析request中的所有上傳内容,并且把每個内容解析成fileItem對象
             * fileItem代表的是普通字段跟檔案字段兩類
             */
            try {
                //使用第三個類

                List<FileItem> fileItemList = servletFileUpload.parseRequest(request);
                for(FileItem fileIem :fileItemList){
                    if(fileIem.isFormField()){
                        //如果說是普通的字段
                        String fileName = fileIem.getFieldName();
                        String fileValue = fileIem.getString("UTF-8");
                        System.out.println(fileName+"-----"+fileValue);
                    }else{
                        //這裡是檔案上傳字段
                        String realFileName = fileIem.getName();
                        /*
                         * 對于ie浏覽器的話上傳路徑是C:\Users\admin\Desktop\1.jpg,
                         * 而對于一些進階浏覽器火狐之類的路徑是1.jpg。
                            是以要對路徑做一個處理。隻需要1.jsp就可以
                         */
                        int index = realFileName.lastIndexOf("\\");
                        if(index>=){
                            //确實是ie浏覽器
                            realFileName = realFileName.substring(index+);
                        }
                        //通過真實的檔案名換算出一個唯一的一個檔案名
                        String makeUuidFileName = makeUuidFileName(realFileName);
                        //通過位運算換算出upload檔案夾下面的子檔案夾
                        String makeUuidFilePath = makeUuidFilePath(uploadPath,makeUuidFileName);

                        /*
                        *在讀取檔案之前可以先進行一系列判斷,如果判斷不通過,不給送出
                        *例如
                        */
                        //如果無上傳檔案
                        if(fileItem.getSize()==){
                            throw new NoUpfileException();
                        }
                        //隻能上傳JPG檔案
                        if(!realFileName.endsWith("JPG")){
                            throw new UpfileTypeException();
                        }
                        //隻有上傳<=200K的檔案
                        if(fileItem.getSize() >  * ){
                            throw new UpfileSizeException();
                        }
                        //等等各種限制條件,自己寫
                        //獲得到檔案輸入流
                        InputStream is = fileIem.getInputStream();
                        //取得檔案輸出流
                        OutputStream os = new FileOutputStream(makeUuidFilePath+"/"+makeUuidFileName);
                        byte[] buf = new byte[];
                        int len = ;
                        while((len = is.read(buf)) >  ){
                            os.write(buf, , len);;
                        }
                        is.close();
                        os.close();
                        //将上傳檔案的臨時檔案删除
                        fileIem.delete();
                        request.setAttribute("message", "上傳成功");
                        request.getRequestDispatcher("/WEB-INF/message.jsp").forward(request, response);
                    }
                }
            } catch (FileUploadException e) {
                e.printStackTrace();
                request.setAttribute("message","上傳檔案失敗");
                request.getRequestDispatcher("/WEB-INF/message.jsp").forward(request,response);
            }   
        }   
    }

    /**
    *這個是防止說一個目錄檔案過多,采用&方式去推出二級目錄之類的函數
    */
    private String makeUuidFilePath(String uploadPath, String makeUuidFileName) {
        String uuidFilePath = null;
        int code = makeUuidFileName.hashCode(); //獲得到檔案的hascode碼  8
        int dir1 = code & ; //3
        int dir2 = code & ; //8
        File file = new File(uploadPath+"/"+dir1+"/"+dir2);
        if(!file.exists()){
            //如果說檔案路徑不存在的話,那麼就一次建立多個目錄
            file.mkdirs();
        }
        uuidFilePath = file.getPath();
        return uuidFilePath;
    }

    /**
     *寫一個算法,給每一張圖檔起一個唯一的名字,這樣在上傳同一張圖檔的時候就可以有多個
     * @param fileName 圖檔的名字,最後加上檔案的名字識别
     * @return
     */
    public String makeUuidFileName(String fileName){
        return UUID.randomUUID().toString()+"_"+fileName;
    }
</font>
           

(二) 第一種重構的方式比較簡單:也就是把原代碼中能夠抽取出來的方法,全部抽取出來放在一個UploadUtil類中,然後再原來的方法中調用該靜态方法就可以

注意:這裡的源碼沒有列舉出來,隻是列舉方法名而已。具體的實作源碼我已經導成了一個jar包。如果有興趣的可以下載下傳該jar包研究一下啊。或者學習者自己重構

//取得上傳的真實路徑和臨時路徑
    public static final String tempPath = "/WEB-INF/temp";
    public static final String uploadPath ="/WEB-INF/upload";

    /*
     * 對于ie浏覽器的話上傳路徑是C:\Users\admin\Desktop\1.jpg,
     * 而對于一些進階浏覽器火狐之類的路徑是1.jpg。
        是以要對路徑做一個處理。隻需要1.jsp就可以
     */
    public static String getRealFileName(String realFileName){
        //代碼忽略了  return 1.jpg
        return realFileName;
    }

    /**取得upload目錄下面的子目錄
     * @param uploadPath  :upload
     * @param makeUuidFileName : a.jpg
     * @return   upload/8/8
     */
    public static String makeUuidFilePath(String uploadPath, String makeUuidFileName) {
        //代碼忽略了 傳回 upload/8/8
        return uuidFilePath;
    }


    /**
     * 取得檔案的uuid名字
     *寫一個算法,給每一張圖檔起一個唯一的名字,這樣在上傳同一張圖檔的時候就可以有多個
     * @param fileName 圖檔的名字,最後加上檔案的名字識别
     * @return
     */
    public static String makeUuidFileName(String fileName){
        return UUID.randomUUID().toString()+"_"+fileName;
    }

    /*
    *檔案儲存,也就是Io流那個
    */
    public static void doSave(InputStream is,String makeUuidFilePath ,String  makeUuidFileName){
        //代碼忽略了 傳回 true/false
        return true/false

    }
           

(三)第二種重構就更加的簡潔了

隻需要調用

UploadUtil.doUpload();

UploadUtil.doSave();

兩個方法就可以實作儲存。

這種簡介的代碼才是我們所追求的。

測試案例:
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        try {
            User user = UploadUtil.doUpload(request);
            String uploadPath = this.getServletContext().getRealPath(UploadUtil.uploadPath);
                UploadUtil.doSave(user,uploadPath);
            request.setAttribute("message", "上傳成功");
            request.getRequestDispatcher("/WEB-INF/message.jsp").forward(request, response);
        } catch (FileUploadException e) {
            e.printStackTrace();
            request.setAttribute("message", "上傳失敗");
            request.getRequestDispatcher("/WEB-INF/message.jsp").forward(request, response);
        }

    }
           
//第二種封裝方式,把上傳檔案分裝成javaBean
    public static User doUpload(HttpServletRequest request) throws Exception{
        //代碼忽略了
        return user;
    }
    //javaBean的儲存檔案
    public static void doSave(User user,String uploadPath) throws IOException{
        //代碼忽略了
    }
           
java之檔案上傳二(源碼)