1. 程式人生 > 其它 >檔案上傳-java web

檔案上傳-java web

第一步:需要引入兩個依賴:common-fileupload和commin-io.

第二步.在web頁面中新增上傳檔案的輸入項

1.必須使用<input type="file">,設定input的name屬性.

    <input type="file" name="file">

2.form表單的enctype必須設定為multipart/form-data.

    enctype="multipart/form-data"

3.form表單的提交方式必須是post.

    method="post"

第三步.編寫servlet,將使用者上傳的資料儲存到本地硬碟.

1.判斷使用者提交的是否是帶檔案的表單,如果是普通的表單中止方法執行,直接返回.

    if(!ServletFileUpload.isMultipartContent(request)){
        return;
    }

2.建立兩個路徑,一個檔案儲存的路徑,一個是檔案儲存的臨時路徑,防止檔案過大佔用硬碟空間.

    String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
    File uploadFile = new File(uploadPath);
    if (!uploadFile.exists()){
        uploadFile.mkdirs();
    }

    String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");
    File file = new File(tmpPath);
    if (!file.exists()){
        file.mkdirs();
    }

3.建立一個DiskFileItempFactory物件,相當於是一個緩衝區,將過大的檔案放入臨時路徑.(將這個過程封裝成方法一,引數是:臨時路徑,返回DiskFileItempFactory物件)

    DiskFileItemFactory factory = getDiskFileItemFactory(file);

4.建立並配置一個ServletFileUpload物件,需要用它來解析前端請求.(將這個過程封裝成方法二,引數是:DiskFileItempFactory物件,返回值:ServletFileUpload物件)

    ServletFileUpload upload = getServletFileUpload(factory);

5.通過ServletFileUpload物件,將前端請求封裝成FileItem物件,FileItem物件可以獲取一個輸入流,將這個流輸出到本地磁碟上,就是使用者上傳的檔案(將這個過程封裝成方法三,引數是:ServletFileUpload物件,前端請求,檔案儲存路徑,返回值:執行結果)

    String message = uploadParseRequest(upload, request, uploadPath);

6.根據執行結果對前端進行反饋,並跳轉頁面.

    if (Objects.equals(message, "檔案上傳成功!")){
        }else {
            message = "請上傳檔案!";
        }
        request.setAttribute("message",message);
        request.getRequestDispatcher("info.jsp").forward(request,response);

方法一

    /**
     * 上傳檔案的緩衝區
     * @param file 臨時檔案路徑
     * @return DiskFileItemFactory物件
     */
    public static DiskFileItemFactory getDiskFileItemFactory(File file) {
        //建立一個DiskFileItemFactory物件
        DiskFileItemFactory factory = new DiskFileItemFactory();
        //設定緩衝區大小為1M
        factory.setSizeThreshold(1024 * 1024);
        //設定臨時檔案的儲存路徑為方法引數中file
        factory.setRepository(file);
        //返回設定好的DiskFileItemFactory物件
        return factory;
    }

方法二

    /**
     * 對建立的ServletFileUpload物件進行配置
     * @param factory 快取區
     * @return 配置好的ServletFileUpload物件
     */
    public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
        //建立ServletFileUpload物件,傳入設定好的快取區物件
        ServletFileUpload upload = new ServletFileUpload(factory);
        // 監聽上傳進度
        upload.setProgressListener(new ProgressListener() {
            public void update(long pBytesRead, long pContentLength, int pItems) {
                System.out.println("總大小:" + pContentLength + "已上傳:" + pBytesRead+",進度:"+((double)pBytesRead/pContentLength)*100+"%");
            }
        });
        // 處理編碼,防止亂碼
        upload.setHeaderEncoding("UTF-8");
        // 設定單個檔案的最大值
        upload.setFileSizeMax(1024 * 1024 * 10);
        //返回ServletFileUpload物件
        return upload;
    }

方法三(核心方法)

    /**
     * 將前端請求中的檔案寫入本地磁碟
     * @param upload ServletFileUpload物件
     * @param request 前端請求
     * @param uploadPath 本地儲存檔案的路徑
     * @return 執行結果
     * @throws FileUploadException 檔案上傳異常
     * @throws IOException IO異常
     */
    public static String uploadParseRequest(ServletFileUpload upload, HttpServletRequest request, String uploadPath) throws FileUploadException, IOException {
        //建立返回結果
        String message = "";
        //利用ServletFileUpload物件將前端請求解析並封裝成FileItem物件,返回一個FileItem物件集
        List<FileItem> fileItems = upload.parseRequest(request);
        //遍歷封裝後的FileItem物件
        for (FileItem fileItem : fileItems) {
            //判斷前端提交的表單有沒有檔案上傳
            if (fileItem.isFormField()) { //沒有檔案上傳
                //getFieldName獲取的的是前端表單控制元件的name;
                String name = fileItem.getFieldName();
                //處理亂碼
                String value = fileItem.getString("UTF-8");
                System.out.println(name + ": " + value);
            } else {// 有檔案上傳

                // ============處理檔名開始==============

                // 拿到檔名
                String uploadFileName = fileItem.getName();
                System.out.println("上傳的檔名: " + uploadFileName);
                //將檔名前後空格去除後,判斷是否為空字串
                if (uploadFileName.trim().equals("")) {
                    continue;
                }
                // 獲取上傳的檔名,將路徑去除,只留下 / 後的字串就是檔案自己的名字 例如: C:\Users\lvjianhua\1.jpg
                String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);
                // 獲得檔案的字尾名,將最後一個點後面的字串獲取,來判斷檔案型別 例如: C:\Users\lvjianhua\1.jpg
                String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);
                //如果檔案字尾名fileExtName不是我們所需要的 就直按return.不處理,告訴使用者檔案型別不對。
                System.out.println("檔案資訊[件名: " + fileName + " ---檔案型別" + fileExtName + "]");

                // ================處理檔名完畢==============

                // ==============處理存放地址開始==============

                // 可以使用UID(唯一識別的通用碼),保證檔名唯一
                // UUID.randomUUID(),這個方法可以隨機生一個唯一識別的通用碼;
                String uuidPath = UUID.randomUUID().toString();
                //用剛才隨機生成的UUID和檔案儲存的路徑拼接一個新路徑,這個路徑就是檔案最後儲存的路徑
                String realPath = uploadPath + "/" + uuidPath;
                //根據這個新路徑建立資料夾,每個檔案都會有一個單獨的資料夾,防止檔案重名,發生覆蓋,
                File realPathFile = new File(realPath);
                //判斷資料夾是否存在
                if (!realPathFile.exists()) {
                    //不存在就生成一個
                    realPathFile.mkdir();
                }

                // ==============存放地址完畢==============

                // =============檔案傳輸開始=============

                //通過FileItem物件獲得檔案上傳的輸入流
                InputStream is = fileItem.getInputStream();
                //建立輸入流,檔案路徑就是,最終存放地址 + 檔名
                FileOutputStream fos = new FileOutputStream(realPath + "/" + fileName);
                //建立一個緩衝區
                byte[] buffer = new byte[1024 * 1024];
                //設定一個int值,來儲存讀取資料的長度
                int len = 0;
                // 一邊讀,一邊寫,如果讀取的資料長度大於0說明還存在資料,就繼續輸出
                while ((len = is.read(buffer)) > 0) {
                    fos.write(buffer, 0, len);
                }
                // 關閉流
                fos.close();
                is.close();
                //執行到此處,說明檔案儲存成功,給返回結果賦值
                message = "檔案上傳成功!";
                //上傳成功,清除臨時檔案
                fileItem.delete();

                //=============檔案傳輸完畢=============

            }
        }
        //返回執行結果
        return message;
    }

第四步.檢視本地磁碟中前端上傳的檔案

檔案上傳的四大注意事項:

  1. 為保證伺服器安全,上傳的檔案應該放在外界無法直接訪問的目錄下,比如放在WEB-INF目錄下
  2. 為防止上傳的檔案發生覆蓋,要為每一個上傳的檔案生成一個唯一的檔名
  3. 限制上傳檔案的大小
  4. 限制上傳檔案的型別,通過檔案的字尾名判斷是否合法