文件上傳與下載----上傳

實現web開發中的文件上傳功能,需完成如下二步操作:

    1、在web頁面中添加上傳輸入項。
   2、在servlet中讀取上傳文件的數據,並保存到本地硬盤中。
      在web頁面中添加上傳輸入項:
              <input type=“file”>標籤用於在web頁面中添加文件上傳輸入項(就會有一個瀏覽按鈕),設置文件上傳輸入項時須注意:
            1、 必須要設置input輸入項的name屬性,否則瀏覽器將不會發送上傳文件的數據。
            2、必須把form的enctype屬值設爲multipart/form-data.設置該值後,瀏覽器在上傳文件時,將把文件數據附帶在http請求消息
                    體中,並使用MIME協議對上傳的文件進行描述,以方便接收方對上傳數據進行解析和處理。
            FORM的enctype屬值multipart/form-data與application/x-www-form-urlencoded的區別 :

                        FORM元素的enctype屬性指定了表單數據向服務器提交時所採用的編碼類型,默認的缺省值是“application/x-www-form-

                    urlencoded”。 然而,在向服務器發送大量的文本、包含非ASCII字符的文本或二進制數據時這種編碼方式效率很低。

                    件上載時,所使用的編碼類型應當是“multipart/form-data”,它既可以發送文本數據,也支持二進制數據上載。Browser

                    端<form>表單的ENCTYPE屬性值爲multipart/form-data,它告訴我們傳輸的數據要用到多媒體傳輸協議,由於多媒體傳

                    輸的都是大量的數據,所以規定上傳文件必須是post方法,<input>的type屬性必須是file。

        在Servlet中讀取文件上傳數據,並保存到本地硬盤中:            
             使用Commons-fileupload組件實現文件上傳,需要導入該組件相應的支撐jar包:Commons-fileupload和commons-io。
             commons-io 不屬於文件上傳組件的開發jar文件,但Commons-fileupload 組件從1.1 版本開始,它工作時需要commons-io包
             的支持。
        爲什麼不用getInputStream方法的原因:
             Request對象提供了一個getInputStream方法,通過這個方法可以讀取到客戶端提交過來的數據。但由於用戶可能會同時上傳
             多個文件,在servlet端編程直接讀取上傳數據,並分別解析出相應的文件數據是一項非常麻煩的工作。爲方便用戶處理文件
             上傳數據,Apache 開源組織提供了一個用來處理表單文件上傳的一個開源組件( Commons-fileupload ),該組件性能優
             異,並且其API使用極其簡單,可以讓開發人員輕鬆實現web文件上傳功能,因此在web開發中實現文件上傳功能,通常使用
             Commons-fileupload組件實現。
核心API—ServletFileUpload
       DiskFileItemFactory 是創建 FileItem 對象的工廠,這個工廠類常用方法:
             public void setSizeThreshold(int sizeThreshold)
             設置內存緩衝區的大小,默認值爲10K。當上傳文件大於緩衝區大小時, fileupload組件將使用臨時文件緩存上傳文件。
             public void setRepository(java.io.File repository)
             指定臨時文件目錄,默認值爲System.getProperty("java.io.tmpdir").
             public DiskFileItemFactory(int sizeThreshold, java.io.File repository)
             構造函數       
       ServletFileUpload 負責處理上傳的文件數據,並將表單中每個輸入項封裝成一個 FileItem 對象中。常用方法有:
             boolean isMultipartContent(HttpServletRequest request)
             判斷上傳表單是否爲multipart/form-data類型
             List parseRequest(HttpServletRequest request)
             解析request對象,並把表單中的每一個輸入項包裝成一個fileItem 對象,並返回一個保存了所有FileItem的list集合。
             setFileSizeMax(long fileSizeMax)
             設置上傳文件的最大值
             setSizeMax(long sizeMax)
             設置上傳文件總量的最大值
             setHeaderEncoding(java.lang.String encoding)
             設置編碼格式
             setProgressListener(ProgressListener pListener)
             獲取進度監視器ProgressListener 對象

上傳文件中應當注意的細節:

        1上傳中文文件的亂碼問題:
             文件名中文亂碼問題,可調用ServletUpLoader的setHeaderEncoding方法,或者設置request的setCharacterEncoding屬性
             l臨時文件的刪除問題
             由於文件大小超出DiskFileItemFactory.setSizeThreshold方法設置的內存緩衝區的大小時,Commons-fileupload組件將使用臨
             時文件保存上傳數據,因此在程序結束時,務必調用FileItem.delete方法刪除臨時文件。
             Delete方法的調用必須位於流關閉之後,否則會出現文件佔用,而導致刪除失敗的情況。
       2上傳的普通輸入項的亂碼問題:

                手工轉碼,用戶名的亂碼問題:

                paramValue= new String(paramValue.getBytes("iso8859-1"),"utf-8");

                利用FileItem類的getString(String encoding)

                 String getString(String encoding)  throws   UnsupportedEncodingException

       3、 文件存放位置問題:
             爲保證服務器安全,上傳文件應保存在應用程序的WEB-INF目錄下,或者不受WEB服務器管理的目錄。
             爲防止多用戶上傳相同文件名的文件,而導致文件覆蓋的情況發生,文件上傳程序應保證上傳文件具有唯一文件名。
             爲防止單個目錄下文件過多,影響文件讀寫速度,處理上傳文件的程序應根據可能的文件上傳總量,選擇合適的目錄
             結構生成算法,將上傳文件分散存儲。

             如表示url資源時應該用斜槓 “/”

             如表示硬盤路徑時用斜槓“\\”

      4、 臨時文件的刪除問題
             代碼必須放在流關閉語句的最後面,因爲正在使用的文件是不能刪除的
             DiskFileItemFactory  factory = new DiskFileItemFactory();

             factory.setRepository(new File(this.getServletContext().getRealPath("/temp")));

                       ……

             FileItem item;

                       ……

             item.delete();

      5、 限制文件上傳的最大值問題:

             調用解析器的:upload.setFileSizeMax(1024*1024);  //上傳文件不能超過1M。如果超出大小,需要給用戶友好提示:

                try{

                        ……

                    }catch (FileUploadBase.FileSizeLimitExceededException e) {

                             request.setAttribute("message", "上傳文件不能超過1M!!");

                    }

       6、 ProgressListener顯示上傳進度問題:    

                    ProgressListener progressListener = new ProgressListener() {

                               public void update(long pBytesRead, long pContentLength, int pItems) {

                                       System.out.println("到現在爲止,  " + pBytesRead + " 字節已上傳,總大小爲 "  + pContentLength);

                               }

                     };

                     upload.setProgressListener(progressListener);
 
實現代碼:
       upload.jsp  

                <form action="${pageContext.request.contextPath}/servlet/UploadServlet2" enctype="multipart/form-data" method="post">

                             用戶名:<input type="text" name="username" /><br/>

                             文件1<input type="file" name="file1" /><br/>

                             文件2<input type="file" name="file2" /><br/>

                            <input type="submit" value="上傳" /><br/>

                </form>

       UploadServlet.java

            package cn.class3g.web.servlet;

            import java.io.File;
            import java.io.FileOutputStream;
            import java.io.IOException;
            import java.io.InputStream;
            import java.io.PrintWriter;
            import java.util.List;
            import java.util.UUID;

            import javax.servlet.ServletException;
            import javax.servlet.http.HttpServlet;
            import javax.servlet.http.HttpServletRequest;
            import javax.servlet.http.HttpServletResponse;

            import org.apache.commons.fileupload.FileItem;
            import org.apache.commons.fileupload.FileUploadBase.FileSizeLimitExceededException;
            import org.apache.commons.fileupload.FileUploadException;
            import org.apache.commons.fileupload.disk.DiskFileItemFactory;
            import org.apache.commons.fileupload.servlet.ServletFileUpload;

            public class UploadServlet2 extends HttpServlet {

                    public void doGet(HttpServletRequest request, HttpServletResponse response)  throws ServletException, IOException {
                             doPost(request,response);
                     }
                   public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  
                           // request.setCharacterEncoding("UTF-8");

                         try {
                              // 1、建立工廠對象
                                  DiskFileItemFactory factory = new DiskFileItemFactory();
                              //factory.setRepository(new File("F:\\"));
   
                              // 2、得到上傳文件解析器
                                  ServletFileUpload upload = new ServletFileUpload(factory);
                                  upload.setHeaderEncoding("utf-8");//處理上傳文件
 
                              // 3、設定上傳文件尺寸
                                   upload.setFileSizeMax(1024*1024);
           
                              // 4、進行解析,得到fileItem對象
                                 List<FileItem> list = upload.parseRequest(request);

                             // 5、對list進行迭代處理
                                 for (FileItem item : list) {
                                     if (item.isFormField()) {// 表單普通輸入項

                                           String paramName = item.getFieldName();
                                        //String paramValue = item.getString();

                                       //paramValue = new String(paramValue.getBytes("ISO8859-1"),"UTF-8");
                                         String paramValue=item.getString("utf-8");
                                         System.out.println("普通輸入項" + paramName + "==" + paramValue);

                                     } else {// 上傳文件處理
                                       //獲取上傳文件名
                                         String fileName = item.getName();
                                       // 如果文件xxx中有目錄,則去掉目錄部分只保留文件名
                                         fileName = fileName.substring(fileName.lastIndexOf("\\") + 1);
                                               System.out.println("name =" + fileName);
     
                                       if (!fileName.equals(" ")) {
      
                                               fileName =refactorFileName(fileName) ;
                                               System.out.println("filename = " + fileName);

                                               InputStream in = item.getInputStream();
                                               File file = new File("F:\\" + fileName);
                                               FileOutputStream fos = new FileOutputStream(file);

                                               byte[] buffer = new byte[1024];
                                               int len = 0;
                                        while ((len - in.read(buffer)) > 0) {
                                                    fos.write(buffer, 0, len);
                                         }

                                        fos.flush();
                                        fos.close();
                                        in.close();
                                        item.delete();
  
                                               request.setAttribute("message", "文件上傳成功");

                                        }
                                      }
                                   }

                                 }catch(FileSizeLimitExceededException e1){
                                                e1.printStackTrace();
                                    request.setAttribute("message", "上傳文件尺寸太大!!!");
                                 }catch (FileUploadException e) {
                                               e.printStackTrace();
                                    request.setAttribute("message", "文件上傳失敗!!!");
                                 }
                                     request.getRequestDispatcher("/message.jsp").forward(request, response);  
                                 }
 
              public String refactorFileName(String fileName){
                      return UUID.randomUUID().toString() + "_" + fileName;  
              }

        }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章