Java Web之文件的上传及下载
一、文件的上傳
1、 簡介
> 將一個客戶端的本地的文件發送到服務器中保存。
> 上傳文件是通過流的形式將文件發送給服務器。
2、表單的設置
1.向服務器上傳一個文件時,表單要使用post請求。
2.表單的默認屬性enctype="application/x-www-form-urlencoded"
- 這個屬性的意思是請求體中的內容將會使用URL編
3. 上傳文件的表單enctype需要設置為 multipart/form-data
- multipart/form-data表示的是表單是一個多部件的表單
- 如果類型設置為它,則我們的每一個表單項都會作為一個單獨的部件發送給服務器。
- 多個部件之間使用類似 -----------------------------7df2d08c0892 分割符來分開
4. 當表單設置為multipart/form-data時,我們request.getParameter()將失效,我們不能再通過該方法獲取請求參數。
3、 FileUpload
1. 我們一般情況下使用commons-fileupload-1.3.1.jar這個工具來解析多部件請求。
2. fileupload 依賴 commons-io 所以我們要是Filtupload需要同時導入io包。
3. 核心類:
DiskFileItemFactory
- 工廠類,用于構建一個解析器實例。
ServletFileUpload
- 解析器類,通過該類實例來解析request中的請求信息。
FileItem
- 工具會將我們請求中每一個部件,都封裝為一個FileItem對象,處理文件上傳時,只需要調用該對象的方法
- 方法:
boolean isFormField() --> 當前表單項是否是一個普通表單項,true是普通表單項, false是文件表單項
String getContentType() --> 返回的是文件的類型,是MIME值:如image/jpeg,text/html
String getFieldName() --> 獲取表單項的name屬性值
String getName() --> 獲取上傳的文件的名字
long getSize() --> 獲取文件的大小
String getString(String encoding) --> 獲取表單項的value屬性值,需要接受一個編碼作為參數。
void write(File file) --> 將表單項中的內容寫入到磁盤中
4、 使用步驟:
1.獲取工廠類實例
2.獲取解析器類實例
3.解析request獲取FileItem
代碼演示:
1 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 2 //1、創建工廠類對象 3 DiskFileItemFactory factory=new DiskFileItemFactory(); 4 //2、創建解析器類對象 5 ServletFileUpload upload=new ServletFileUpload(factory); 6 7 upload.setFileSizeMax(1024*50); //設置單個文件的大小為50K 8 upload.setSizeMax(1024*120); //設置上傳總文件的大小為120K 9 10 List<FileItem> list=new ArrayList<FileItem>(); 11 try { 12 //3、解析請求部件 13 list=upload.parseRequest(request); 14 for(FileItem fileItem:list){ 15 if(fileItem.isFormField()){ //判斷是否為普通表單項 16 String name=fileItem.getFieldName(); //獲取name屬性名 17 String value=fileItem.getString(); //獲取name屬性值 18 System.out.println(name+":"+value); 19 }else { //文件表單項 20 long size = fileItem.getSize(); //獲取文件大小 21 if(size>0){ 22 String name=fileItem.getFieldName(); //獲取name屬性名 23 String fileName=fileItem.getName(); //獲取文件名 24 if(fileName.contains("\\")){ //截取文件名 25 fileName=fileName.substring(fileName.lastIndexOf("\\")+1); 26 } 27 //解決文件名重復問題,使用uuid,在文件名前加上uuid,防止重復 28 String uuid=UUID.randomUUID().toString().replace("-",""); 29 fileName=uuid+"_"+fileName;//加上"_",便于截串 30 String contentType = fileItem.getContentType(); //獲取文件類型 31 32 System.out.println("name屬性名為:"+name); 33 System.out.println("文件名為:"+fileName); 34 System.out.println("文件類型為:"+contentType); 35 System.out.println("文件大小為:"+size); 36 37 ServletContext context=request.getServletContext(); //獲取上下文對象 38 String realPath = context.getRealPath("/upload"); //獲取文件真實路徑 39 File file=new File(realPath); //按照路徑創建目錄 40 if(!file.exists()){ //目錄不存在 41 file.mkdirs(); //創建目錄 42 } 43 //將上傳的文件保存到指定目錄下 44 fileItem.write(new File(realPath+"/"+fileName)); 45 } 46 } 47 } 48 } catch(FileSizeLimitExceededException e){ 49 request.setAttribute("msg", "單個文件超出50k"); 50 request.getRequestDispatcher("/upload.jsp").forward(request, response); 51 } catch (SizeLimitExceededException e) { 52 request.setAttribute("msg", "文件大小超出120k"); 53 request.getRequestDispatcher("/upload.jsp").forward(request, response); 54 }catch (Exception e) { 55 e.printStackTrace(); 56 } 57 } 文件上傳4、 細節
1.第一個問題:> 部分瀏覽器會將文件的完整路徑作為文件名發送。
C:\Users\lilichao\Desktop\day20\圖片\蒙娜麗莎.jpg
> 像這類文件名我們需要截取一下字符串,只獲取名字這部分,而不需要獲取路徑部分的信息。
通過如下代碼對文件名進行截取字符串的操作:
1 if(name.contains("\\")){ //如果包含則截取字符串 2 name = name.substring(name.lastIndexOf("\\")+1); 3 }2.第二個問題:上傳的文件有可能出現重名,后上傳的文件會將先上傳的文件覆蓋。
> 解決:給文件名加一個唯一的前綴。
唯一標識_fennu.jpg
UUID_fennu.jpg
1 //解決文件名重復問題,使用uuid,在文件名前加上uuid,防止重復 2 String uuid=UUID.randomUUID().toString().replace("-",""); 3 fileName=uuid+"_"+fileName;//加上"_",便于截串?
3.第三個問題:有些情況需要限制上傳文件的大小。
- 設置單個文件大小為50KB:
fileUpload.setFileSizeMax(1024*50);
- 設置完單個文件大小限制以后,一旦上傳的文件超過限制,則會拋出如下異常:
FileSizeLimitExceededException
-所以可以對該異常進行捕獲,當出現該異常時則設置一個錯誤消息。
- 設置多個文件的總大小為150KB
fileUpload.setSizeMax(1024*150);
- 當多個文件的大小超出范圍時,會拋出如下異常
SizeLimitExceededException
4.第四個問題:?當用戶上傳一個空的文件,依然會將文件保存到硬盤上。
> 在保存文件應該先對文件的大小進行判斷,如果size為0,則不處理。
二、文件的下載
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來解碼的,所以要為火狐單獨處理。
1. 可以使用如下代碼來判斷瀏覽器的類型,然后進行不同的編碼處理
1 String ua=request.getHeader("User-Agent");//獲得請求頭瀏覽器信息 2 //判斷當前瀏覽器是否為火狐 3 if(ua.contains("Firefox")){ 4 //是火狐瀏覽器,使用BASE64編碼 5 fileName = "=?utf-8?b?"+new BASE64Encoder().encode(fileName.getBytes("utf-8"))+"?="; 6 }else{ 7 //給文件名進行URL編碼 8 //URLEncoder.encode()需要兩個參數,第一個參數時要編碼的字符串,第二個是編碼所采用的字符集 9 fileName = URLEncoder.encode(fileName, "utf-8"); 10 }? 2. ?還有一種不太講理的方式,誰問跟誰急。反正好使
- 向將字符串用gbk進行解碼,然后在使用iso8859-1進行編碼
fileName = new String(fileName.getBytes("gbk"),"iso8859-1");
代碼演示:
?
轉載于:https://www.cnblogs.com/java-zmj/p/7928731.html
總結
以上是生活随笔為你收集整理的Java Web之文件的上传及下载的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mybatis中使用mysql的模糊查询
- 下一篇: 浏览器是如何展示网页的