程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> JavaEE組件commons-fileupload完成文件上傳、下載

JavaEE組件commons-fileupload完成文件上傳、下載

編輯:關於JAVA

JavaEE組件commons-fileupload完成文件上傳、下載。本站提示廣大學習愛好者:(JavaEE組件commons-fileupload完成文件上傳、下載)文章只能為提供參考,不一定能成為您想要的結果。以下是JavaEE組件commons-fileupload完成文件上傳、下載正文


1、文件上傳概述

完成Web開辟中的文件上傳功效,須要兩步操作:

1、在Web頁面中添加上傳輸出項

    <form action="#" method="post" enctype="multipart/form-data">
      <input type="file" name="filename1"/><br>
      <input type="file" name="filename2"/><br>
      <input type="submit" value="上傳"/>
    <form>
    <!-- 1、表雙方式必需是post
      2、必需設置encType屬性為 multipart/form-data.設置該值後,閱讀器在上傳文件時,將會把文件數據附帶在http要求新聞體中,
        並應用MIME協定對上傳的文件停止描寫,以便利吸收方對上傳數據停止解析和處置。
      3、必需要設置input的name屬性,不然閱讀器將不會發奉上傳文件的數據。
    -->

2、在Servlet中讀取文件上傳數據,並保留到辦事器硬盤

Request對象供給了一個getInputStream辦法,經由過程這個辦法可以讀取到客戶端提交過去的數據。但因為用戶能夠會同時上傳多個文件,在Servlet端編程直接讀取上傳數據,並分離解析出響應的文件數據是一項異常費事的任務。

好比上面是截取的閱讀器上傳文件時發送的要求的HTTP協定中的部門內容:        

Accept-Language: zh-Hans-CN,zh-Hans;q=0.5
Content-Type: multipart/form-data; boundary=---------------------------7dfa01d1908a4
UA-CPU: AMD64
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.2; Win64; x64; Trident/7.0; rv:11.0) like Gecko
Content-Length: 653
Host: localhost:8080
Connection: Keep-Alive
Pragma: no-cache
Cookie: JSESSIONID=11CEFF8E271AB62CE676B5A87B746B5F
-----------------------------7dfa01d1908a4
Content-Disposition: form-data; name="username"
zhangsan
-----------------------------7dfa01d1908a4
Content-Disposition: form-data; name="userpass"
1234
-----------------------------7dfa01d1908a4
Content-Disposition: form-data; name="filename1"; filename="C:\Users\ASUS\Desktop\upload.txt"
Content-Type: text/plain
this is first file content!
-----------------------------7dfa01d1908a4
Content-Disposition: form-data; name="filename1"; filename="C:\Users\ASUS\Desktop\upload2.txt"
Content-Type: text/plain
this is Second file content!
hello
-----------------------------7dfa01d1908a4--

 從下面的數據中也能夠看出,假如本身手工的去朋分讀取數據很難寫出硬朗穩固的法式。所以,為便利用戶處置上傳數據,Apache開源組織供給了一個用來處置表單文件上傳的一個開源組件(Commons-fileupload),該組件機能優良,而且其API應用極端簡略,可讓開辟人員輕松完成web文件上傳功效,是以在web開辟中完成文件上傳功效,平日應用Commons-fileupload組件完成。

 須要導入兩個jar包:Commons-fileupload、commons-io

response.setContentType("text/html;charset=utf-8");//設置呼應編碼
    request.setCharacterEncoding("utf-8");
    PrintWriter writer = response.getWriter();//獲得呼應輸入流
    
    ServletInputStream inputStream = request.getInputStream();//獲得要求輸出流
    
    /*
     * 1、創立DiskFileItemFactory對象,設置緩沖區年夜小和暫時文件目次
     *  該類有兩個結構辦法一個是無參的結構辦法,
     *  另外一個是帶兩個參數的結構辦法
     * @param int sizeThreshold,該參數設置內存緩沖區的年夜小,默許值為10K。當上傳文件年夜於緩沖區年夜小時,fileupload組件將應用暫時文件緩存上傳文件
     * @param java.io.File repository,該參數指定暫時文件目次,默許值為System.getProperty("java.io.tmpdir");
     * 
     *  假如應用了無參的結構辦法,則應用setSizeThreshold(int sizeThreshold),setRepository(java.io.File repository)
     *  辦法手動停止設置 
     */
    DiskFileItemFactory factory = new DiskFileItemFactory();
    
    int sizeThreshold=1024*1024;
    factory.setSizeThreshold(sizeThreshold);
    
    File repository = new File(request.getSession().getServletContext().getRealPath("temp"));
//    System.out.println(request.getSession().getServletContext().getRealPath("temp"));
//    System.out.println(request.getRealPath("temp"));
    factory.setRepository(repository);
    
    /*
     * 2、應用DiskFileItemFactory對象創立ServletFileUpload對象,並設置上傳文件的年夜小
     *  
     *  ServletFileUpload對象擔任處置上傳的文件數據,並將表單中每一個輸出項封裝成一個FileItem
     *  該對象的經常使用辦法有:
     *      boolean isMultipartContent(request);斷定上傳表單能否為multipart/form-data類型
     *      List parseRequest(request);解析request對象,並把表單中的每個輸出項包裝成一個fileItem 對象,並前往一個保留了一切FileItem的list聚集
     *      void setFileSizeMax(long filesizeMax);設置單個上傳文件的最年夜值
     *      void setSizeMax(long sizeMax);設置上傳溫江總量的最年夜值
     *      void setHeaderEncoding();設置編碼格局,處理上傳文件名亂碼成績
     */
    ServletFileUpload upload = new ServletFileUpload(factory);
    
    upload.setHeaderEncoding("utf-8");//設置編碼格局,處理上傳文件名亂碼成績
    /*
     * 3、挪用ServletFileUpload.parseRequest辦法解析request對象,獲得一個保留了一切上傳內容的List對象
     */
    List<FileItem> parseRequest=null;
    try {
       parseRequest = upload.parseRequest(request);
    } catch (FileUploadException e) {
      e.printStackTrace();
    }
    /*
     * 4、對list停止迭代,每迭代一個FileItem對象,挪用其isFormField辦法斷定能否是文件上傳
     *  true表現是通俗表單字段,則挪用getFieldName、getString辦法獲得字段名和字段值
     *  false為上傳文件,則挪用getInputStream辦法獲得數據輸出流,從而讀取上傳數據
     *  
     *  FileItem用來表現文件上傳表單中的一個上傳文件對象或許通俗的表單對象
     *  該對象經常使用辦法有:
     *     boolean isFormField();斷定FileItem是一個文件上傳對象照樣通俗表單對象
     *     true表現是通俗表單字段,
     *         則挪用getFieldName、getString辦法獲得字段名和字段值
     *     false為上傳文件,
     *         則挪用getName()取得上傳文件的文件名,留意:有些閱讀器會攜帶客戶端途徑,須要本身減除
     *         挪用getInputStream()辦法獲得數據輸出流,從而讀取上傳數據
     *         delete(); 表現在封閉FileItem輸出流後,刪除暫時文件。
     */
    
    for (FileItem fileItem : parseRequest) {
      if (fileItem.isFormField()) {//表現通俗字段
        if ("username".equals(fileItem.getFieldName())) {
          String username = fileItem.getString();
          writer.write("您的用戶名:"+username+"<br>");
        }
        if ("userpass".equals(fileItem.getFieldName())) {
          String userpass = fileItem.getString();
          writer.write("您的暗碼:"+userpass+"<br>");
        }
        
      }else {//表現是上傳的文件
        //分歧閱讀器上傳的文件能夠帶有途徑名,須要本身切割
        String clientName = fileItem.getName();
        String filename = "";
        if (clientName.contains("\\")) {//假如包括"\"表現是一個領路徑的名字,則截取最初的文件名
          filename = clientName.substring(clientName.lastIndexOf("\\")).substring(1);
        }else {
          filename = clientName;
        }
        
        UUID randomUUID = UUID.randomUUID();//生成一個128位長的全球獨一標識
        
        filename = randomUUID.toString()+filename;
        
        /*
         * 設計一個目次生成算法,假如所用用戶上傳的文件總數是億數目級的或更多,放在統一個目次下回招致文件索引異常慢,
         * 所以,設計一個目次構造來疏散寄存文件長短常有需要,且公道的
         * 將UUID取哈希算法,散列到更小的規模,
         * 將UUID的hashcode轉換為一個8位的8進制字符串,
         * 從這個字符串的第一名開端,每個字符代表一級目次,如許就構建了一個八級目次,每級目次中最多有16個子目次
         * 這不管關於辦事器照樣操作體系都長短常高效的目次構造
         */
        int hashUUID =randomUUID.hashCode();
        String hexUUID = Integer.toHexString(hashUUID);
        //System.out.println(hexUUID);
        //獲得將上傳的文件存存儲在哪一個文件夾下的相對途徑
        String filepath=request.getSession().getServletContext().getRealPath("upload");
        for (char c : hexUUID.toCharArray()) {
          filepath = filepath+"/"+c;
        }
        //假如目次不存在就生成八級目次
        File filepathFile = new File(filepath);
        if (!filepathFile.exists()) {
          filepathFile.mkdirs();
        }
        //從Request輸出流中讀取文件,並寫入到辦事器
        InputStream inputStream2 = fileItem.getInputStream();
        //在辦事器端創立文件
        File file = new File(filepath+"/"+filename);
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
        
        byte[] buffer = new byte[10*1024];
        int len = 0;
        while ((len= inputStream2.read(buffer, 0, 10*1024))!=-1) {
          bos.write(buffer, 0, len);
        }
        writer.write("您上傳文件"+clientName+"勝利<br>");
        //封閉資本
        bos.close();
        inputStream2.close();
      }
    }
  //留意Eclipse的上傳的文件是保留在項目標運轉目次,而不是workspace中的工程目次裡。

 2、文件上傳須要特殊留意的成績: (這些成績在下面的代碼中都供給了簡略的處理)

1、文件寄存的地位

為包管辦事器的平安,上傳文件應保留在運用法式的WEB-INF目次下,或許不受WEB辦事器治理的目次,假如用戶上傳一個帶有可履行代碼的文件,如jsp文件,依據拼接拜訪途徑去拜訪的話,可以在辦事器端做任何工作。

2、為避免多用戶上傳形同文件名的文件,而招致文件籠罩的情形產生,文件上傳法式應包管上傳文件具有獨一文件名。

應用UUID + 用戶上傳文件名的方法重定名

關於UUID:
UUID(Universally Unique Identifier)全局獨一標識符,是指在一台機械上生成的數字,它包管對在統一時空中的一切機械都是獨一的。依照開放軟件基金會(OSF)制訂的尺度盤算,用到了以太網卡地址、納秒級時光、芯片ID碼和很多能夠的數字。由以下幾部門的組合:以後日期和時光(UUID的第一個部門與時光有關,假如你在生成一個UUID以後,過幾秒又生成一個UUID,則第一個部門分歧,其他雷同),時鐘序列,全局獨一的IEEE機械辨認號(假如有網卡,從網卡取得,沒有網卡以其他方法取得),UUID的獨一缺點在於生成的成果串會比擬長。

是一個128位長的數字,普通用16進制表現。算法的焦點思惟是聯合機械的網卡、本地時光、一個隨即數來生成GUID。從實際上講,假如一台機械每秒發生10000000個GUID,則可以包管(幾率意義上)3240年不反復。

從JDK1.5開端,生成UUID釀成了一件簡略的事,認為JDK完成了UUID:

java.util.UUID,直接挪用便可.
UUID uuid  =  UUID.randomUUID();
String s = UUID.randomUUID().toString();//用來生成數據庫的主鍵id異常不錯。。 
 
UUID是由一個十六位的數字構成,表示出來的情勢例如
550E8400-E29B-11D4-A716-446655440000 

3、為避免單個目次下文件過量,影響文件讀寫速度,處置上傳文件的法式應當應依據能夠的上傳總量,選擇適合的目次構造生成算法,將上傳文件疏散存儲。如應用hashcode辦法構建多級目次。

4、假如分歧用戶都上傳了雷同的文件,那末在辦事器端沒有需要存儲統一個文件的許多分拷貝,如許很糟蹋資本,應當設盤算法處理這類反復文件的成績。

5、JSP技巧道理主動完成了多線程。所以開辟者不須要斟酌上傳文件的多線程操作 

3、文件下載 

<%
    ArrayList<String> fileNames = new ArrayList<String>();
    fileNames.add("file/aa.txt");
    fileNames.add("file/bb.jpg");
    for(String fileName : fileNames) {
   %>
   
    <form action="DownloadServlet" method="get">
      <input type="hidden" name="fileName" value="<%=fileName %>" />
      <input type="submit" value="下載:<%=fileName %>" />
    </form>
   <%
    }
   %>
 
    request.setCharacterEncoding("utf-8");
    
    String filename = request.getParameter("fileName");
    
    
    String urlname = URLEncoder.encode(filename, "utf-8");//避免文件名中有中文亂碼
    response.setHeader("Content-Disposition","attachment;filename="+urlname);
    
    FileInputStream fis = new FileInputStream(new File(request.getSession().getServletContext().getRealPath(filename)));
    BufferedInputStream bis = new BufferedInputStream(fis);
    ServletOutputStream sos = response.getOutputStream();
    
    byte[] buffer = new byte[1024];
    int len=0;
    while((len=bis.read(buffer, 0, 1024))!=-1){
      sos.write(buffer, 0, len);
    }
    bis.close();
    fis.close();

4、在SSH中應用smartUpload組件簡化文件上傳下載

以上就是本文的全體內容,願望對年夜家的進修有所贊助,也願望年夜家多多支撐。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved