国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

JavaEE組件commons-fileupload實現文件上傳、下載

2019-11-26 13:42:49
字體:
來源:轉載
供稿:網友

一、文件上傳概述

實現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.5Content-Type: multipart/form-data; boundary=---------------------------7dfa01d1908a4UA-CPU: AMD64Accept-Encoding: gzip, deflateUser-Agent: Mozilla/5.0 (Windows NT 6.2; Win64; x64; Trident/7.0; rv:11.0) like GeckoContent-Length: 653Host: localhost:8080Connection: Keep-AlivePragma: no-cacheCookie: JSESSIONID=11CEFF8E271AB62CE676B5A87B746B5F-----------------------------7dfa01d1908a4Content-Disposition: form-data; name="username"zhangsan-----------------------------7dfa01d1908a4Content-Disposition: form-data; name="userpass"1234-----------------------------7dfa01d1908a4Content-Disposition: form-data; name="filename1"; filename="C:/Users/ASUS/Desktop/upload.txt"Content-Type: text/plainthis is first file content!-----------------------------7dfa01d1908a4Content-Disposition: form-data; name="filename1"; filename="C:/Users/ASUS/Desktop/upload2.txt"Content-Type: text/plainthis 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("http://")) {//如果包含"/"表示是一個帶路徑的名字,則截取最后的文件名          filename = clientName.substring(clientName.lastIndexOf("http://")).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中的工程目錄里。

 二、文件上傳需要特別注意的問題: (這些問題在上面的代碼中都提供了簡單的解決)

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技術原理自動實現了多線程。所以開發者不需要考慮上傳文件的多線程操作 

三、文件下載 

<%    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();

四、在SSH中使用smartUpload組件簡化文件上傳下載

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 新竹县| 清新县| 永吉县| 大新县| 平舆县| 克拉玛依市| 犍为县| 临汾市| 安顺市| 华池县| 陆河县| 通江县| 建湖县| 元江| 祁东县| 鄯善县| 绥滨县| 河津市| 义乌市| 大荔县| 略阳县| 上蔡县| 合水县| 长顺县| 砀山县| 肇东市| 孝感市| 南雄市| 凌源市| 砀山县| 天门市| 平阴县| 古蔺县| 宁波市| 织金县| 茂名市| 依兰县| 象山县| 金阳县| 马鞍山市| 鄯善县|