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組件簡化文件上傳下載
以上就是本文的全體內容,願望對年夜家的進修有所贊助,也願望年夜家多多支撐。