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

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

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

    隨筆-48  評(píng)論-26  文章-0  trackbacks-0

    核心API-DiskFileItemFactory:

         DiskFileItemFactory是創(chuàng)建FileItem對(duì)象的工廠,這個(gè)工廠常用方法:

    1.      public DiskFileItemFactory(int sizeThreshold, java.io.File repository),常用的構(gòu)造函數(shù)。

    2.      public void setSizeThreshold(int sizeThreshold),設(shè)置內(nèi)存緩沖區(qū)的大小,默認(rèn)值為10K。當(dāng)上傳文件大于緩沖區(qū)大小時(shí), fileupload組件將使用臨時(shí)文件緩存上傳文件。

    3.      public void setRepository(java.io.File repository),指定臨時(shí)文件目錄,默認(rèn)值為System.getProperty("java.io.tmpdir")。

            

    核心API-ServletFileupLoad:

    ServletFileUpload 負(fù)責(zé)處理上傳的文件數(shù)據(jù),并將表單中每個(gè)輸入項(xiàng)封裝到一個(gè)FileItem對(duì)象中。常用方法有:

    1.      boolean isMultipartContent(HttpServletRequest request),判斷上傳表單是否為上傳表單類型。

    2.      List parseRequest(HttpServletRequest request),解析request對(duì)象,并把表單中的每一個(gè)輸入項(xiàng)包裝到一個(gè)fileItem 對(duì)象中,并返回一個(gè)保存了所有FileItem的list集合。

    3.      setFileSizeMax(long fileSizeMax),設(shè)置上傳文件的最大尺寸值。

    4.      setSizeMax(long sizeMax),設(shè)置上傳文件總量的最大值。

    5.      setHeaderEncoding(java.lang.String encoding),設(shè)置編碼格式。如果文件路徑中存在中文可能會(huì)造成文件路徑亂碼,用此方法處理可以解決。

    6.      setProgressListener(ProgressListener pListener),設(shè)置進(jìn)程監(jiān)聽器,與AWT和Swing的事件處理機(jī)制一樣。文件上傳一點(diǎn)就會(huì)觸發(fā)ProgressListener,這樣我們就可以獲取文件上傳的進(jìn)度。

    上傳文件案例:

    public class FileuploadServlet extends HttpServlet {

        public void doGet(HttpServletRequest request, HttpServletResponse response)

               throws ServletException, IOException {

           // 創(chuàng)建文件處理工廠,它用于生成FileItem對(duì)象。

           DiskFileItemFactory difactory = new DiskFileItemFactory();

           //設(shè)置緩存大小,如果上傳文件超過緩存大小,將使用臨時(shí)目錄做為緩存。

           difactory.setSizeThreshold(1024 * 1024);

           // 設(shè)置處理工廠緩存的臨時(shí)目錄,此目錄下的文件需要手動(dòng)刪除。

           String dir = this.getServletContext().getRealPath("/");

           File filedir = new File(dir + "filetemp");

           if (!filedir.exists())

               filedir.mkdir();

           difactory.setRepository(filedir);

           // 設(shè)置文件實(shí)際保存的目錄

           String userdir = dir + "files";

           File fudir = new File(userdir);

           if (!fudir.exists())

               fudir.mkdir();

           // 創(chuàng)建request的解析器,它會(huì)將數(shù)據(jù)封裝到FileItem對(duì)象中。

           ServletFileUpload sfu = new ServletFileUpload(difactory);

           // 解析保存在request中的數(shù)據(jù)并返回list集合

           List list = null;

           try {

               list = sfu.parseRequest(request);

           } catch (FileUploadException e) {

               e.printStackTrace();

           }

           // 遍歷list集合,取出每一個(gè)輸入項(xiàng)的FileItem對(duì)象,并分別獲取數(shù)據(jù)

           for (Iterator it = list.iterator(); it.hasNext();) {

               FileItem fi = (FileItem) it.next();

               if (fi.isFormField()) {

                  System.out.println(fi.getFieldName());

                  System.out.println(fi.getString());

               } else {

                  //由于客戶端向服務(wù)器發(fā)送的文件是客戶端的全路徑,在這我們只需要文件名即可

                  String filename = fi.getName();

                  int index = filename.lastIndexOf("""");

                  if(index != -1)

                      filename = filename.substring(index+1);

                  //向服務(wù)器寫出文件

                  InputStream in = fi.getInputStream(); 

                  FileOutputStream fos = new FileOutputStream(fudir + "/" +filename);

                  byte[] buf = newbyte[1024];

                  int len = -1;

                  while((len = in.read(buf)) != -1){

                      fos.write(buf, 0, len);

                  }

                  // 關(guān)閉流

                  if(in != null){

                      try{

                         in.close();

                      }finally{

                         if(fos!=null)

                             fos.close();

                      }

                  }

               }

           }

        }

        public void doPost(HttpServletRequest request, HttpServletResponse response)

               throws ServletException, IOException {

           doGet(request, response);

        }

    }

    上面的代碼只是功能的練習(xí),實(shí)際開發(fā)中的文件上傳需要考慮諸多因素,我們接下來繼續(xù)學(xué)習(xí)。

        

    JS動(dòng)態(tài)添加文件上傳框和按鈕的JavaScript代碼:

    function add(){

              var file = document.createElement("input");

              file.type = "file";

              file.name = "file";

             

              var butt = document.createElement("input");

              butt.type = "button";

              butt.value = "刪除";

              butt.onclick = function rem(){

              //必須使用按鈕的父節(jié)點(diǎn)DIV的父節(jié)點(diǎn)來刪除自己和自己的父節(jié)點(diǎn)DIV

                  this.parentNode.parentNode.removeChild(this.parentNode);

              };

             

              var div = document.createElement("div");

              div.appendChild(file);

              div.appendChild(butt);

             

              var parent = document.getElementById("files");

              parent.appendChild(div);

           }

    上傳文件的處理細(xì)節(jié)(1):

    1.      中文文件亂碼的問題,可以調(diào)用兩個(gè)方法來設(shè)置字符編碼:servletUpLoader.setHeaderEncoding()或request.setCharacterEncoding()。我們可以在源文件的創(chuàng)建ServletFileUpload對(duì)象后邊添加如下代碼:

    sfu.setHeaderEncoding("UTF-8");

    2.      臨時(shí)文件的刪除,如果臨時(shí)文件大于setSizeThreshold設(shè)置的緩存大小,Commons-fileupload組件將使用setRepository設(shè)置的臨時(shí)目錄來保存上傳的文件,上傳完成后我們需要手動(dòng)調(diào)用FileItem.delete來刪除臨時(shí)文件。建議不要修改緩存區(qū)大小,如果設(shè)置緩存為1MB,1000個(gè)用戶上傳文件就需要1000MB內(nèi)存,服務(wù)器會(huì)受不了的。我們刪除掉setSizeThreshold的代碼,并在每次完成一個(gè)文件后添加下而的代碼:

    // 刪除臨時(shí)目錄中的文件

    fi.delete();

    上傳文件的處理細(xì)節(jié)(2):

    1.      在上面的代碼中,我們將文件的實(shí)際保存目錄設(shè)置在WEB-INF目錄之外。這樣外部可以直接訪問被上傳的文件,這會(huì)造成安全問題。比如用戶上傳了一個(gè)帶有惡意腳本功能的JSP文件,然后從外部訪問執(zhí)行了JSP文件…后果不堪設(shè)想。所以我們將源代碼中對(duì)應(yīng)位置處修改如下:

    // 之所以放在"WEB-INF"目錄下是為了防止上傳的文件被直接被訪問的安全問題

    String userdir = dir + "WEB-INF/files";

    2.      一個(gè)WEB應(yīng)用會(huì)許多不同的用戶訪問,不同的用戶可能會(huì)上傳相同名稱的文件,如果這樣可能會(huì)造成文件覆蓋的情況發(fā)生,所以我們必須保證文件名稱的唯一性,我編寫一個(gè)方法來生成唯一性名稱的文件名:

    /**

         *生成具有唯一性的UUID文件名稱

         *@paramfileName

         *@return

         */

        private String uuidName(String fileName){

           UUID uuid = UUID.randomUUID();

           return uuid.toString() + "_" + fileName;

        }

    我們將代碼“filename = filename.substring(index + 1);”修改為:filename = uuidName(filename.substring(index + 1));

    3.      如果一個(gè)目錄下的文件過多,會(huì)極大減慢文件的訪問速度。比如一個(gè)目錄下的文件如果超過1000個(gè),達(dá)到1萬個(gè)呢?恐怖!我們必須編寫一個(gè)目錄結(jié)構(gòu)生成算法,來分散存上傳的文件。我們一個(gè)方法:

        /**

         *使用哈希算法生成的文件路徑

         *@paramdir

         *@paramfileName

         *@return

         */

        private String hashPath(String dir, String fileName) {

           int hashCode = fileName.hashCode();

          

           int dir1 = (hashCode >> 4) & 0xf;

           int dir2 = hashCode & 0xf;

          

           String newpath = dir + "/" + dir1 + "/" + dir2 + "/";

           File file = new File(newpath);

           if(!file.exists()){

               file.mkdirs();

           }

          

           return newpath + uuidName(fileName);

        }

    上傳文件的處理細(xì)節(jié)(3)

    1.      使用ProgressListener顯示上傳文件進(jìn)度,在創(chuàng)建ServletFileUpload之后添加如下代碼:

    // 設(shè)置文件上傳進(jìn)度監(jiān)聽器

           sfu.setProgressListener(new ProgressListener() {

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

                  System.out.println("已上傳:" + pBytesRead + "總大小:"

                         + pContentLength);

               }

    });

    2.      上面的代碼會(huì)造成頻繁的打印,為了使它在上傳一定數(shù)量后再打印,比如上傳10KB后再打印,我們修改上面的代碼如下:

    // 設(shè)置文件上傳進(jìn)度監(jiān)聽器

           sfu.setProgressListener(new ProgressListener() {

               longtemp = -1;

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

                  long size = pBytesRead / 1024 * 1024 * 10;

                  if(temp == size)

                      return;

                  temp = size;

                  if(pBytesRead != -1)

                      System.out.println("已上傳:" + pBytesRead + "總大小:"

                         + pContentLength);

                  else

                      System.out.println("上傳完成!");

               }

    });

    上面的代碼比較經(jīng)典,好好回味一下。

    文件下載:

        WEB應(yīng)用中實(shí)現(xiàn)文件下載的兩種方式:

    1.         超鏈接直接指向下載資源

    2.         程序?qū)崿F(xiàn)下載需設(shè)置兩個(gè)響應(yīng)頭:

    (1). 設(shè)置Content-Type 的值為:application/x-msdownload。Web 服務(wù)器需要告訴瀏覽器其所輸出的內(nèi)容的類型不是普通的文本文件或 HTML 文件,而是一個(gè)要保存到本地的下載文件。

    (2). Web 服務(wù)器希望瀏覽器不直接處理相應(yīng)的實(shí)體內(nèi)容,而是由用戶選擇將相應(yīng)的實(shí)體內(nèi)容保存到一個(gè)文件中,這需要設(shè)置 Content-Disposition 報(bào)頭。該報(bào)頭指定了接收程序處理數(shù)據(jù)內(nèi)容的方式,在 HTTP 應(yīng)用中只有 attachment 是標(biāo)準(zhǔn)方式,attachment 表示要求用戶干預(yù)。在 attachment 后面還可以指定 filename 參數(shù),該參數(shù)是服務(wù)器建議瀏覽器將實(shí)體內(nèi)容保存到文件中的文件名稱。在設(shè)置 Content-Dispostion 之前一定要指定 Content-Type。

         為實(shí)現(xiàn)文件下載,首先我們遍歷目錄下所有文件,Servlet:

    import java.io.File;

    import java.io.IOException;

    import java.util.HashMap;

    import javax.servlet.ServletException;

    import javax.servlet.http.HttpServlet;

    import javax.servlet.http.HttpServletRequest;

    import javax.servlet.http.HttpServletResponse;

    public class ListFileServlet extends HttpServlet {

        public void doGet(HttpServletRequest request, HttpServletResponse response)

               throws ServletException, IOException {

           // 獲取目錄

           String dir = this.getServletContext().getRealPath("/WEB-INF/files");

           HashMap map = new HashMap();

           listFile(new File(dir), map);

           // 將文件列表設(shè)置到request的屬性中,然后由JSP頁(yè)面打印列表。

           request.setAttribute("filemap", map);

           request.getRequestDispatcher("/list.jsp").forward(request, response);

        }

        /**

         *使用遞歸算法,將所有子目錄中的文件添加到列表中

         *

         *@paramf

         *@paraml

         */

        private void listFile(File f, HashMap map) {

           if (f.isFile()) {

               String path = f.getAbsolutePath().substring(

                      this.getServletContext().getRealPath("/").length());

               String name = f.getName();

               name = name.substring(name.indexOf("_")+1);         

               //BASE64Encoder encoder = new BASE64Encoder();

               map.put(path, name);

           } else {

               File[] files = f.listFiles();

               for (int i = 0; i < files.length; i++) {

                  listFile(files[i], map);

               }

           }

        }

        public void doPost(HttpServletRequest request, HttpServletResponse response)

               throws ServletException, IOException {

           doGet(request, response);

        }

    }
    posted on 2009-12-02 14:14 Worker 閱讀(477) 評(píng)論(0)  編輯  收藏 所屬分類: J2SE/J2EE

    主站蜘蛛池模板: 亚洲日韩一区精品射精| 亚洲综合久久1区2区3区| 亚洲国产老鸭窝一区二区三区 | 国产亚洲sss在线播放| 精品久久久久久亚洲综合网| 免费福利在线观看| 永久免费不卡在线观看黄网站| 99精品视频免费观看| 无码高潮少妇毛多水多水免费| 亚洲成A人片在线观看中文 | 免费中文字幕在线| 亚洲成AV人片在线观看无码| 亚洲免费视频播放| 精品一区二区三区免费毛片| 亚洲免费观看视频| 毛片免费全部免费观看| 亚洲精品在线视频| 亚洲理论片在线观看| 老司机午夜在线视频免费观| 久草免费手机视频| 免费无码又爽又高潮视频 | 亚洲日韩亚洲另类激情文学| kk4kk免费视频毛片| 亚洲免费观看在线视频| 免费国产a国产片高清网站| 亚洲AV永久无码精品一百度影院| 亚洲三级在线免费观看| 一道本在线免费视频| 91九色老熟女免费资源站| 亚洲?v女人的天堂在线观看| 亚洲精品在线不卡| 无码免费又爽又高潮喷水的视频 | 99无码人妻一区二区三区免费| 免费a级毛片网站| 亚洲欧洲国产视频| 免费的黄色的网站| 国产又大又粗又长免费视频| 久久久久亚洲精品天堂久久久久久| 亚洲中文字幕人成乱码 | 亚洲电影免费在线观看| 日本免费一二区在线电影|