<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                [TOC] # 頁面注意 設置文件上傳輸入項時須注意: * 必須要設置input輸入項的name屬性,否則瀏覽器將不會發送上傳文件的數據。 * 必須把form的enctype屬值設為`multipart/form-data`。設置該值后,瀏覽器在上傳文件時,將把文件數據附帶在http請求消息體中,并使用MIME協議對上傳的文件進行描述,以方便接收方對上傳數據進行解析和處理。 現在我們設計一個這樣的文件上傳頁面——upload.jsp ~~~ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <form action="${pageContext.request.contextPath }/UploadServlet" 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="上傳"> </form> </body> </html> ~~~ 此時表單的提交方式應該為POST,因為請求方式為POST方式,則可以在請求的實體內容中向服務器發送數據,即文件數據將附帶在http請求消息體中。 # Servlet處理請求 接下來如何在Servlet中讀取文件上傳數據,并保存到本地硬盤中呢? 答案應該是這樣的:Request對象提供了一個getInputStream方法,通過這個方法可以讀取到客戶端提交過來的數據。但由于用戶可能會同時上傳多個文件,在servlet端編程直接讀取上傳數據,并分別解析出相應的文件數據是一項非常麻煩的工作。 ~~~ public class UploadServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { InputStream in = request.getInputStream(); int len = 0; byte[] buffer = new byte[1024]; while ((len=in.read(buffer)) > 0) { System.out.println(new String(buffer, 0, len)); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } ~~~ 這時我們再次輸入上傳用戶名和兩個文件,Eclipse的控制臺輸出如下: ~~~ -----------------------------24566388929294 Content-Disposition: form-data; name="username" aaa -----------------------------24566388929294 Content-Disposition: form-data; name="file1"; filename="涓婁紶鏂囦歡1.txt" Content-Type: text/plain aaaaaaaaaa -----------------------------24566388929294 Content-Disposition: form-data; name="file2"; filename="涓婁紶鏂囦歡2.txt" Content-Type: text/plain bbbbbbbbb -----------------------------24566388929294-- ~~~ 這時我們在servlet端編程直接讀取上傳數據,并分別解析出相應的文件數據是一項非常麻煩的工作。為方便用戶處理文件上傳數據,Apache開源組織提供了一個用來處理表單文件上傳的一個開源組件( Commons-fileupload ),該組件性能優異,并且其API使用極其簡單,可以讓開發人員輕松實現web文件上傳功能,因此在web開發中實現文件上傳功能,通常使用Commons-fileupload組件實現。 # 導入Commons-fileupload 使用Commons-fileupload組件實現文件上傳,需要導入該組件相應的支撐jar包:Commons-fileupload和commons-io。commons-io不屬于文件上傳組件的開發jar文件,但Commons-fileupload組件從1.1版本開始,它工作時需要commons-io包的支持。 我們從網上下載了這兩個jar包 * commons-fileupload.jar * commons-io-2.5.jar # fileupload組件工作流程 fileupload組件工作流程如圖所示: ![](https://box.kancloud.cn/a5da7b6a677966e14b143a574075aa10_766x348.png) ## 核心API—DiskFileItemFactory 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):構造函數 ## 核心API—ServletFileUpload 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) ## 中文亂碼 上傳文件的中文亂碼問題: * 解決上傳文件的中文亂碼:ServletFileUpload.setHeaderEncoding(“UTF-8”) * 解決普通輸入項的中文亂碼(注意,表單類型為multipart/form-data的時候,設置request的編碼是無效的):FileItem.setString("UTF-8") ## 注意事項 **在處理表單之前須判斷提交表單的類型** 如果處理文件上傳的UploadServlet一上來不管三七二十一就劈頭蓋臉地用解析器進行解析數據,而不管表單類型是不是multipart/form-data。 顯然這樣做是不合理的。合理的做法應該是:在處理表單之前,要記得調用ServletFileUpload.isMultipartContent方法判斷提交表單的類型,如果該方法返回true,則按上傳方式處理,否則按照傳統方式處理表單即可 **當上傳文件大于緩沖區大小時, fileupload組件將使用臨時文件緩存上傳文件** DiskFileItemFactory是創建FileItem對象的工廠,其內存緩沖區的大小默認為10K,當上傳文件大于緩沖區大小時, fileupload組件將使用臨時文件緩存上傳文件。比方說我們要上傳一部電影,電影通常都在幾百兆左右,這么大的一個文件顯然就已經超出了內存緩沖區的大小,那這個時候我們可以使用臨時文件來緩存上傳文件。 我們在項目的WebRoot根目錄下新建一個保存臨時文件的目錄——temp。 我們可以設置DiskFileItemFactory的內存緩沖區大小為1M,即內存緩沖區開辟1M大小的空間。如果上傳文件沒有超過1M,那么fileupload組件將使用內存緩沖區緩存上傳文件;如果上傳文件超過1M,那么fileupload組件將使用臨時文件緩存上傳文件。那么代碼就應該是這樣的: ~~~ DiskFileItemFactory factory = new DiskFileItemFactory(); factory.setSizeThreshold(1024*1024); ~~~ 然后還要指定臨時文件的目錄,那代碼就應該是這樣的: ~~~ factory.setRepository(new File(this.getServletContext().getRealPath("/temp"))); ~~~ **上傳文件的保存目錄** 大家在做上傳文件時,總該會想我們上傳的文件會保存在哪兒吧?絕大部分的程序員可能會在WebRoot根目錄下新建一個upload目錄,在此目錄下保存上傳的文件 **判斷文件擴展名** 我們在做文件上傳系統的時候,可以限制上傳文件的類型,如我這個文件上傳系統只支持XXX.jpg、XXX.gif、XXX.avi、XXX.txt等格式的文件上傳,其他格式的文件我是拒絕的。要做到這點其實不難,只要在處理上傳文件時,判斷上傳文件的后綴名是不是允許的即可 **限制上傳文件的大小** 我們也可以設置單個上傳文件的大小,只要超出我們設置的值,就不讓其上傳,并給用戶以友好提示。 有些人還是要以身試險的,如我調用解析器的setFileSizeMax方法設置上傳文件的最大值為5M,即ServletFileUpload.setFileSizeMax(1024*1024*5);,只要有人上傳的文件大于5M,試想解析器在解析這份文件時,應如何做呢?可以想見,解析器就會拋出一個異常,翻閱Commons-fileupload組件的文檔,就能找到這樣一個異常:FileUploadBase.FileSizeLimitExceededException,不錯,我們就是要拋它,然后程序員通過是否抓到這個異常,進而就可以給用戶友好提示 **為防止文件覆蓋的現象發生,要為上傳文件產生一個唯一的文件名** 我們在上傳文件系統的時候,要考慮到多用戶上傳相同文件名的文件,而導致文件覆蓋的情況發生的問題。為了避免上傳文件的覆蓋,程序在保存上傳文件時,要為每一個文件生成一個唯一的文件名 ## 例子 最后我們要編寫處理文件上傳的Servlet。我們可以按照下面的步驟將它擼出來。 1. 創建DiskFileItemFactory對象,設置緩沖區大小和臨時文件目錄,也即創建解析工廠。 2. 使用DiskFileItemFactory對象創建ServletFileUpload對象,并設置上傳文件的大小限制,也即創建解析器。 3. 調用ServletFileUpload.parseRequest方法解析request對象,得到一個保存了所有上傳內容的List對象。 4. 對list進行迭代,每迭代一個FileItem對象,調用其isFormField方法判斷是否是上傳文件。 1. 為普通表單字段,則調用getFieldName、getString方法得到字段名和字段值。 2. 為上傳文件,則調用getInputStream方法得到數據輸入流,從而讀取上傳數據。 ~~~ public class UploadServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // List<String> types = Arrays.asList(".jpg",".gif",".avi",".txt"); List<String> types = Arrays.asList("jpg","gif","avi","txt"); // request.setCharacterEncoding("UTF-8"); try { DiskFileItemFactory factory = new DiskFileItemFactory(); factory.setSizeThreshold(1024*1024); factory.setRepository(new File(this.getServletContext().getRealPath("/temp"))); ServletFileUpload upload = new ServletFileUpload(factory); upload.setProgressListener(new ProgressListener() { // update方法一定要由解析器來調用 @Override public void update(long pBytesRead, long pContentLength, int pItems) { System.out.println("當前已解析:" + pBytesRead); } }); // 限制上傳文件的大小 upload.setFileSizeMax(1024*1024*5); // 只要超出5M,for循環在解析的時候就會拋異常 // 提交的表單類型不是multipart/form-data,沒必要用解析器進行解析數據,按照傳統方式獲取表單數據 if (!upload.isMultipartContent(request)) { // 按照傳統方式獲取表單數據 request.getParameter("username"); blabla...... return; } // 解決上傳文件的中文亂碼問題,設置解析器的編碼,到底設什么編碼,也不能瞎寫,一定要看表單的數據是以什么編碼提交的! upload.setHeaderEncoding("UTF-8"); List<FileItem> list = upload.parseRequest(request); for (FileItem item : list) { if (item.isFormField()) { // 為普通輸入項的數據 String inputName = item.getFieldName(); String inputValue = item.getString("UTF-8"); // inputValue = new String(inputValue.getBytes("ISO8859-1"), "UTF-8"); System.out.println(inputName + "=" + inputValue); } else { // 代表當前處理的item里面封裝的是上傳文件 String fileName = item.getName().substring(item.getName().lastIndexOf("\\")+1); if (fileName == null || fileName.trim().equals("")) { continue; } // 拿到文件的擴展名 String ext = fileName.substring(fileName.lastIndexOf(".")+1); if (!types.contains(ext)) { request.setAttribute("message", "本系統不支持" + ext + "這種類型"); request.getRequestDispatcher("/message.jsp").forward(request, response); return; } InputStream in = item.getInputStream(); int len = 0; byte[] buffer = new byte[1024]; // 得到保存在服務器中唯一的文件名 String saveFileName = generateFileName(fileName); // 產生文件的保存目錄 String savePath = generateSavePath(this.getServletContext().getRealPath("/WEB-INF/upload"), saveFileName); FileOutputStream out = new FileOutputStream(savePath + File.separator + saveFileName); while ((len=in.read(buffer)) > 0) { out.write(buffer, 0, len); } in.close(); out.close(); /* * 上傳文件完了之后,刪除臨時文件, * 千萬注意:這句代碼一定要放在流關閉之后,否則,還有流和它相關聯,那就刪除不掉臨時文件, * 為了確保流關閉、刪除掉臨時文件,最好把這些代碼放到finally代碼塊中。 */ item.delete(); } } } catch (FileUploadBase.FileSizeLimitExceededException e) { e.printStackTrace(); request.setAttribute("message", "文件大小不能超過5M"); request.getRequestDispatcher("/message.jsp").forward(request, response); return; } catch (Exception e) { throw new RuntimeException(e); } request.setAttribute("message", "上傳成功!!!"); request.getRequestDispatcher("/message.jsp").forward(request, response); } public String generateSavePath(String path, String fileName) { int hashCode = fileName.hashCode(); // 得到字符串在內存中的地址,如121221 int dir1 = hashCode & 15; // int dir1 = hashCode & 0xf; 代表一級目錄 int dir2 = (hashCode >> 4) & 0xf; // 代表二級目錄 // 用戶第一次上傳文件,此savePath目錄在服務器的硬盤里原本是沒有的,所以應將其創建出來 String savePath = path + File.separator + dir1 + File.separator + dir2; File file = new File(savePath); if (!file.exists()) { file.mkdirs(); // 創建多級目錄用mkdirs()方法 } return savePath; } public String generateFileName(String fileName) { // 4de727e8-2579-477f-a4ae-658355f107fe return UUID.randomUUID().toString() + "_" + fileName; } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看