JavaWeb 文件的上傳、下載

来源:https://www.cnblogs.com/chy18883701161/archive/2019/08/27/11417710.html
-Advertisement-
Play Games

文件上傳 表單 指定<form>的method="post", enctype="multipart/form-data"。 accept指定文件類型,有多種類型時逗號分隔,multiple指定可以選擇多個文件。 傳統處理方式 選擇的文件是放在請求消息體中的。獲取的輸入流中包含了上傳的所有文件,如果 ...


 

文件上傳

表單

<form action="HandlerServlet" method="post" enctype="multipart/form-data">
請選擇要上傳的文件:<input type="file" name="uploadFile" accept="*/*" multiple /><br />
<button type="submit">上傳</button>
</form>

指定<form>的method="post", enctype="multipart/form-data"。

accept指定文件類型,有多種類型時逗號分隔,multiple指定可以選擇多個文件。

 

 

傳統處理方式

ServletInputStream inputStream = request.getInputStream();

選擇的文件是放在請求消息體中的。獲取的輸入流中包含了上傳的所有文件,如果單個上傳還好處理,如果同時上傳多個,不好從中分離出單個文件的數據,且自己寫代碼獲取文件名很麻煩。

 

 

 

Commons-FileUpload

Commons-FileUpload是Apache的開源組件,提供了一套處理上傳文件的API。

 

使用FileUpload需要2個jar包:

  • commons-fileupload.jar     
  • commons-io.jar    這是FileUpload依賴的IO包,要單獨下載添加。

 

FileUpload組件主要的介面、類:

  • DiskFileItemFactory類     將請求消息實體中的每一個參數都封裝為單獨的FileItem對象
  • ServletFileUpload類     調用DiskFileItemFactory類來封裝請求參數,並對封裝好的FileItem做進一步處理,以List<FileItem>形式返回
  • FileItem介面   用於封裝請求參數,提供了一系列操作上傳文件的方法。

 

 

DiskFileItemFactory類的常用方法

  • DiskFileItemFactory()    //空參的構造方法,使用預設臨界值、系統臨時文件夾
  • DisFileItemfactory(int  size, File  repository)   //帶參的構造方法,指定臨界值、緩存目錄

 

  • FileItem  createItem()   //將一個請求參數封裝為FileItem,並返回封裝好的FileItem。這個方法由DiskFileItemFactory內部自動調用。不用我們管。

 

  • set|SizeThreshold(int  size)   //設置臨界值
  • setRepository(File  repository)    //設置緩存目錄。這2個方法都要對應的get方法。

 

JVM的記憶體是有限的,比如用戶上傳一個1G的文件,直接保存在JVM記憶體中,實打實地占用伺服器記憶體,這絕對不行。

臨界值指定文件大小,小於臨界值的文件直接存儲在JVM記憶體中,大於臨界值的文件,以臨時文件(.tmp)的形式保存在緩存目錄中。預設為10240,預設單位Byte,即10KB。

緩存目錄可以指定為磁碟上的某一個文件夾,以File形式指定,不指定時預設使用系統的臨時文件夾。

 

 

 

ServletFileUpload類的常用方法

  • ServletFileUpload()    //空參構造器
  • ServletFileUpload(FileItemFactory fileItemFactory)   //帶參的構造器,指定使用的FileItemFactory對象。FileItemFactory是介面,一般使用它的實現類DiskFileItemFactory(上面那個類)。

 

  • setFileItemFactory(FileItemFactory fileItemFactory)
  • setSizeMax(long  size)   //設置請求消息實體內容(傳遞的所有請求參數)的最大尺寸,防止用戶惡意上傳超大文件浪費伺服器存儲空間。預設單位Byte。
  • setFileSizeMax(long size)   //設置單個文件的最大尺寸
  • setHeaderEncoding("utf-8")    //設置請求參數的字元集,未設置時使用HttpServletRequest設置的字元集,若HttpServletRequest也未設置字元集,則使用系統預設的字元集。

以上幾個setter()方法均有對應的getter()方法。

 

  • List<FileItem>   parseRequest(HttpServletRequest  request)    //調用FileItemFactory對象的方法,開始封裝每個請求參數,以List<FileItem>形式返回封裝好的所有的請求參數
  • FileItemIterator  getItemIterator(HttpServletRequest  request)   //同上,只是返回的是迭代器

 

註意:是封裝每一個請求參數,不是只封裝上傳的文件,所以有些FileItem保存的是普通的請求欄位。

 

 

FileItem介面常用的方法

  •  boolean  isFormField()    //判斷這個FileItem封裝的是不是普通的表單欄位
  • String getFieldName()   //獲取欄位名,即表單控制項的name屬性
  • String  getName()   //獲取上傳文件的文件名(帶有尾碼,比如:1.jpg),如果封裝的是普通的表單欄位,得到是null
  • long getSize()   //獲取文件的大小,預設單位位元組
  • String getContentType()   //獲取文件類型,比如image/jpeg
  • boolean  isInMemory()    //是否存儲在JVM記憶體中。如果存儲在記憶體中,返回true;存儲在緩存目錄中,返回false。

 

  • void  write(File  file)    //將上傳文件寫到伺服器的磁碟中。如果此文件是存儲在緩存目錄中的,寫完會自動刪除緩存目錄中對應的臨時文件。
  • InputStream getInputStream()   //獲取輸入流
  • void  delete()  //清除FileItem存儲的主體內容,如果存儲在緩存目錄中,會刪除緩存目錄中對應的臨時文件。雖然GC會自動清除不再使用的臨時文件,但使用完立即刪除是最好的。

 

 

 

Servlet處理上傳文件示例

 1 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 2         response.setContentType("text/html;charset=utf-8");
 3 
 4         //創建FileItemFactory對象
 5         DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
 6         File tempFolder=new File("E:/tempFolder");   //Java中的File即指文件,又指文件夾
 7         if (!tempFolder.exists()){  //不存在就新建
 8             tempFolder.mkdir();
 9         }
10         //指定緩存目錄
11         diskFileItemFactory.setRepository(tempFolder);  
12 
13         //創建ServletFileUpload對象
14         ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
15         //指定編碼字元集
16         servletFileUpload.setHeaderEncoding("utf-8");
17 
18         try {
19             //獲取List<FileItem>
20             List<FileItem> fileItems = servletFileUpload.parseRequest(request);
21             for (FileItem fileItem:fileItems){
22                 if(!fileItem.isFormField()){  //是上傳文件
23                     //使用UUID創建唯一的文件名
24                     String fileName= UUID.randomUUID().toString()+"_"+fileItem.getName();
25                     String path="C:/Users/chy/Desktop/upload/"+fileName;
26                     fileItem.write(new File(path));  //寫到伺服器磁碟上。寫完會自動刪除臨時文件。
27                 }
28             }
29 
30         } catch (FileUploadException e) {
31             e.printStackTrace();
32         } catch (Exception e) {
33             e.printStackTrace();
34         }
35 
36 
37     }

 

 

 

 

 

文件下載

最簡單的方式:使用<a>標簽直接鏈接到文件地址。

<a href="http://www.xxx.com/resource/特斯拉.mp4">下載xxx</a>

有2個問題:

  • 某些類型的文件,比如jpg、mp3、mp4、txt等會直接在網頁中打開、播放,而非下載。
  • 如果以後資源地址換了,比如換ftp伺服器了、改資源路徑了,需要一個個地修改<a>連接的href屬性,十分麻煩。

 

 

解決方式:

(1)鏈接到Servlet,並傳遞文件名。

<a href="downloadServlet?fileName=特斯拉.mp4">下載xxx</a>

 

(2)Servlet

 1 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 2         request.setCharacterEncoding("utf-8");
 3         response.setContentType("text/html;charset=utf-8");
 4 
 5         String fileName = request.getParameter("fileName");
 6         //對文件名進行iso8859-1編碼
 7         String browerFileName=new String(fileName.getBytes("utf-8"),"iso8859-1");
 8 
 9         //指定瀏覽器行為為下載
10         response.addHeader("Content-Type","application/octet-stream");
11         //指定下載文件名。註意這兩個都是addHeader(),不是setHeader()
12         response.addHeader("Content-Disposition","attachment;filename="+browerFileName);
13 
14         InputStream is = getServletContext().getResourceAsStream("resource/"+fileName);  //換路徑時只需修改此句中的路徑,不用修改每個<a>
15         ServletOutputStream os= response.getOutputStream();
16         byte[] buffer = new byte[1024];
17         int len;
18         while ((len=is.read(buffer))!= -1){  //註意是-1,不是0
19             os.write(buffer);
20         }
21 
22     }

 

紅字是為瞭解決下載文件名中文亂碼。

因為我們使用的是utf-8字元集,而chrome這些瀏覽器預設使用 iso8859-1 字元集。要轉換一下,這樣瀏覽器在設置下載文件名時才能識別文件名中的中文。

 

 

其實 <a href="downloadServlet?fileName=特斯拉.mp4">下載xxx</a> ,url中的中文也要轉換一下,一個中文字元轉換為%xxxx的形式(%後面跟著4個十六進位數)。

<a href="downloadServlet?fileName=<%=URLEncoder.encode("特斯拉.mp4","utf-8")%>">下載</a>

String  URLEncoder.encode(String  str, String  charset)    //靜態方法,返回編碼後的字元串

當然,不轉換也行,都能正確識別。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 08.27自我總結 Vue的介紹及安裝和導入 一Vue的介紹 進式 JavaScript 框架 三大主流框架之一:Angular React Vue 先進的前端設計模式:MVVM 這個我們可以和之前的 設置模式結合其實他相當於mvcmc他將其中的邏輯控制又進行劃分劃分成視圖的邏輯,數據的邏輯. 可以 ...
  • 來,講故事: 單體架構(1): 小藍創辦了一家公司,由於資金緊張,招聘了小白負責行政,小紅負責財務,小黑負責技術,小黃負責運營,5個人擼起袖子就是乾,準備向市場推一個 “××寶” 的產品。 實際上每個人職責界限都不那麼明確,小白忙了小紅幫,小紅忙了小黑幫,小黑忙了沒人幫,小黃不忙到處幫,小藍組織幫幫 ...
  • 在上一篇博文中,我們見證了 IP 地址的誕生,機器一旦有了 IP,就可以在網路的環境里和其他的機器展開溝通了。 今天,我們來認識下 物理層 和 MAC 層。 日常生活中,身為 90 後的我們,如果不是通信相關專業出身的,應該從來沒有接觸過物理層和 MAC 層的設備。我們接觸最多的,可能就是路由器了。 ...
  • 瞭解完網路協議,我們會發現,網路通信的五層模型里,有兩個很重要的概念:IP 地址和 MAC 地址。 那麼 IP 地址是怎麼來的,又是怎麼沒的?MAC 地址與 IP 地址又有什麼區別? 這回答上面問題前,先熱下身,大家知道如何查看本機的 IP 嗎?這個問題,即便是沒有專業學過電腦的人,只要折騰過電腦 ...
  • 今天開始學習設計模式,藉此機會學習並整理學習筆記。 設計模式是一門不區分語言的課程,什麼樣的編程語言都可以用到設計模式。如果說java語法規則比作武功招式的話,那麼設計模式就是心法。 設計模式共有23種,常見的19種,最常用的9-10種。 設計模式分三種類型:創建型、結構型、行為型; 其中創建型包含 ...
  • 在內置函數(dict、list、set、tuple)的基礎上,collections模塊還提供了幾個其他的數據類型:Counter、deque、defaultdict、namedtuple和OrdereDict等 1.namedtuple 作用:用於生成一個可以使用名字訪問元素內容的tuple 如果 ...
  • 思前想後一個月,我終於敲下了我的第一篇開山之作。 博客千千萬,我的博客首先記錄的是學習時候的理解,用於給自己翻閱查找,現在主要研究的是C語言和STM32。如果能幫到你,那是最好的,假如我寫的東西有錯誤歡迎指正,所以請反覆對比,僅作參考。其次,這裡不僅記錄學習,也會寫下我在朋友圈不能公開的想法和秘密! ...
  • 一、共用變數 共用變數:當多個線程訪問同一個變數的時候。會產生共用變數的問題。 例子: 正如上面的結果可以看出:並不是我們期望的0,而是-286705,這就是因為我們共用變數了,同時對變數進行了操作,程式並不是原子的。 2.解決方案:使用“鎖”,“信號燈” (1)鎖lock:是一個標誌,表示一個線程 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...