Java上傳和下載
1.文件的上傳
[1] 簡介
> 將一個客戶端的本地的文件發送到服務器中保存。
> 上傳文件是通過流的形式將文件發送給服務器。
[2] 表單的設置
> 向服務器上傳一個文件時,表單要使用post請求。
> 表單的默認屬性enctype="application/x-www-form-urlencoded"
- 這個屬性的意思是請求體中的內容將會使用URL編碼
> 上傳文件的表單enctype需要設置為 multipart/form-data
- multipart/form-data表示的是表單是一個多部件的表單
- 如果類型設置為它,則我們的每一個表單項都會作為一個單獨的部件發送給服務器。
- 多個部件之間使用類似 -----------------------------7df2d08c0892 分割符來分開
> 當表單設置為multipart/form-data時,我們request.getParameter()將失效,我們不能再通過該方法獲取請求參數。
[3] FileUpload
> 我們一般情況下使用commons-fileupload-1.3.1.jar這個工具來解析多部件請求。
> fileupload 依賴 commons-io 所以我們要是Filtupload需要同時導入io包。
> 核心類: DiskFileItemFactory
- 工廠類,用於構建一個解析器實例。 ServletFileUpload
- 解析器類,通過該類實例來解析request中的請求信息。 FileItem
- 工具會將我們請求中每一個部件,都封裝為一個FileItem對象,處理文件上傳時,只需要調用該對象的方法
- 方法:
boolean isFormField() --> 當前表單項是否是一個普通表單項,true是普通表單項, false是文件表單項
String getContentType() --> 返回的是文件的類型,是MIME值
String getFieldName() --> 獲取表單項的name屬性值
String getName() --> 獲取上傳的文件的名字
long getSize() --> 獲取文件的大小
String getString(String encoding) --> 獲取表單項的value屬性值,需要接受一個編碼作為參數。
void write(File file) --> 將表單項中的內容寫入到磁盤中
> 使用步驟:
1.獲取工廠類實例[DiskFileItemFactory]
2.獲取解析器類實例[ServletFileUpload]
3.解析request獲取FileItem[parseRequest()]
[4] 細節
第一個問題
> 部分瀏覽器會將文件的完整路徑作為文件名發送。
C:\Users\lilichao\Desktop\day20\圖片\蒙娜麗莎.jpg
> 像這類文件名我們需要截取一下字符串,只獲取名字這部分,而不需要獲取路徑部分的信息。
通過如下代碼對文件名進行截取字符串的操作:
if(name.contains("\\")){
//如果包含則截取字符串
name = name.substring(name.lastIndexOf("\\")+1);
}
第二個問題
> 上傳的文件有可能出現重名,後上傳的文件會將先上傳的文件覆蓋。
> 解決:給文件名加一個唯一的前綴。 唯一標識_fennu.jpg UUID_fennu.jpg
第三個問題
> 有些情況需要限制上傳文件的大小。
- 設置單個文件大小為50KB: fileUpload.setFileSizeMax(1024*50);
- 設置完單個文件大小限制以後,一旦上傳的文件超過限制,則會拋出如下異常:
FileSizeLimitExceededException
所有可以對該異常進行捕獲,當出現該異常時則設置一個錯誤消息。
- 設置多個文件的總大小為150KB fileUpload.setSizeMax(1024*150);
- 當多個文件的大小超出範圍時,會拋出如下異常 SizeLimitExceededException
第四個問題
> 當用戶上傳一個空的文件,依然會將文件保存到硬盤上。
> 在保存文件應該先對文件的大小進行判斷,如果size為0,則不處理。
2.文件的下載
[1] 簡介
> 將服務器中的文件下載到本地。
> 一般情況下資源所在的鏈接發送給瀏覽器,瀏覽器就會自動下載。
但是當瀏覽器支持當前文件的格式,瀏覽器會自動打開文件,而不會彈出下載窗口。
> 直接將資源放在項目的目錄下,瀏覽器可以直接訪問到資源。
所以一般我們下載的資源不能讓瀏覽器直接訪問到。
[2] 下載所需要的內容
1.獲取到文件的流
2.設置兩個響應頭
[3] 下載相關的兩個響應頭
1) 文件類型 Content-Type --> 文件的MIME類型
Content-Type:告訴瀏覽器文件的類型,需要設置一個MIME值
response.setContent-Type("MIME值") 通過servletContext.getMimeType(path)方法可以直接獲取文件的MIME類型
2) 下載文件的信息 Content-Disposition --> attachment; filename=文件名
Content-Disposition告訴瀏覽器如何處理文件
attachment 告訴瀏覽器這個文件是一個附件的形式發給你的,需要你做下載的操作
filename 告訴瀏覽器下載文件的名字
3) 亂碼的問題,當將文件的名字設置為中文,瀏覽器正常顯示文件的名字。
因為從服務器向瀏覽器發送中文時,需要對內容進行URL編碼。
> 大部分瀏覽器使用如下方式即可解決亂碼問題:URLEncoder.encode(fileName, "utf-8");
> 但是火狐默認以Base64來解碼的,所以要為火狐單獨處理。
> 可以使用如下代碼來判斷瀏覽器的類型,然後進行不同的編碼處理
//判斷當前瀏覽器是否為火狐
if(ua.contains("Firefox")){ //是火狐瀏覽器,使用BASE64編碼 fileName = "=?utf-8?b?"+new BASE64Encoder().encode(fileName.getBytes("utf-8"))+"?="; }else{ //給文件名進行URL編碼 //URLEncoder.encode()需要兩個參數,第一個參數時要編碼的字符串,第二個是編碼所采用的字符集 fileName = URLEncoder.encode(fileName, "utf-8"); }
> 還有一種不太講理的方式,反正好使
- 向將字符串用gbk進行解碼,然後在使用iso8859-1進行編碼
fileName = new String(fileName.getBytes("gbk"),"iso8859-1");
Java上傳和下載