javaWeb學習總結——文件上傳、下載
@
嘿,熊dei,你不得不知道在Web開發中,文件上傳和下載功能是非常常用的功能,關於文件上傳,瀏覽器上傳【文件以流的形式傳輸】——>服務器端——>Servlet獲取上傳文件的輸入流——>解析請求參數,這一系列過程下來我這佩奇腦殼都疼,因此我更 推薦用apache的開源工具common-fileupload這個文件上傳組件 ,common-fileupload上傳組件的jar包可以去apache官網上面下載,也可以在struts的lib文件夾下面找到(不要問我爲什麼,因爲就算你問我我也不會告訴你struts上傳功能就是基於這個實現,當然你也不一定用過Struts【現在不用去學,用的少了】,再者你也不會這麼閒去lib目錄找),其次 common-fileupload 依賴於 common-io 包,所以需要一起下載使用!
1、文件上傳環境搭建
jar包下載,可以直接搜索apche官網進行下載,不過現在比較流行mawen管理jar包(不懂mawen?加油吧,要學的東西還很多,mawen是一定要學的而且也很易學,用了mawen你就停不下來,這玩意太便捷了,學會了mawen,你就會明白媽媽爲什麼再也不用擔心小明拿U盤去拷小紅的jar包了)
這個時候common-fileupload依賴的common-io包同樣的操作進行下載,之後創建項目,引入jar包
2、文件上傳代碼實現
2.1JSP代碼
<%@ 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="UploadServet" method="post" enctype="multipart/form-data"> 學號:<input name="sno" /><br/> 姓名:<input name="sname" /><br/> 上傳照片: <input type="file" name="spicture"/> <br/> <input type="submit" value="註冊"/> </form> <a href="DownloadServlet?filename=MIME.png">MIME</a> </body> </html>
2.2Servlet代碼
package org.student.servlet; import java.io.File; import java.io.IOException; import java.util.Iterator; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileItemFactory; import org.apache.commons.fileupload.FileUploadBase; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; /** * Servlet implementation class UploadServet */ public class UploadServet extends HttpServlet { private static final long serialVersionUID = 1L; public UploadServet() { super(); } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse * response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); response.setContentType("text/html; charset=UTF-8"); // 上傳 // request.getParameter("sname") try { boolean isMultipart = ServletFileUpload.isMultipartContent(request); if (isMultipart) {// 判斷前臺的form是否有 mutipart屬性 // FileItemFactory factory = new DiskFileItemFactory(); DiskFileItemFactory factory = new DiskFileItemFactory(); ServletFileUpload upload = new ServletFileUpload(factory); //設置上傳文件時 用到的臨時文件的大小DiskFileItemFactory factory.setSizeThreshold(10240);//設置臨時的緩衝文件大小爲10 factory.setRepository(new File("D:\\study\\uploadtemp"));//設置臨時文件的目錄 //控制上傳單個文件的大小 20KB ServletFileUpload upload.setSizeMax(20480);//字節B Thread.sleep(3000); // 通過parseRequest解析form中的所有請求字段,並保存到 items集合中(即前臺傳遞的sno sname // spicture此時就保存在了items中) List<FileItem> items = upload.parseRequest(request); // 遍歷items中的數據(item=sno sname spicture) Iterator<FileItem> iter = items.iterator(); while (iter.hasNext()) { FileItem item = iter.next(); String itemName = item.getFieldName(); int sno = -1; String sname = null; // 判斷前臺字段 是普通form表單字段(sno sname),還是文件字段 // request.getParameter() -- iter.getString() if (item.isFormField()) { if (itemName.equals("sno")) {// 根據name屬性 判斷item是sno sname 還是spicture? sno = Integer.parseInt(item.getString("UTF-8")); } else if (itemName.equals("sname")) { sname = item.getString("UTF-8"); } else { System.out.println("其他字段xxx....."); } } else {// spicture 123 // 文件 上傳 // 文件名 getFieldName是獲取 普通表單字段的Name值 // getName()是獲取 文件名 String fileName = item.getName();//a.txt a.docx a.png String ext = fileName.substring( fileName.indexOf(".")+1 ) ; if(!(ext.equals("png") || ext.equals("gif") ||ext.equals("jpg"))) { System.out.println("圖片類型有誤!格式只能是 png gif jpg"); return ;//終止 } // 獲取文件內容 並上傳 // 定義文件路徑:指定上傳的位置(服務器路徑) // 獲取服務器路徑D:\\study\\apache-tomcat-8.5.30\\wtpwebapps\\UpAndDown\\upload // String path =request.getSession().getServletContext().getRealPath("upload") ; String path = "D:\\study\\upload"; File file = new File(path, fileName); item.write(file);// 上傳 System.out.println(fileName + "上傳成功!"); return; } } } } catch (FileUploadBase.SizeLimitExceededException e) {//SizeLimitExceededException是FileUploadException的一個子類 System.out.println("上傳文件大小超過限制!最大20KB"); } catch (FileUploadException e) { e.printStackTrace(); } // 解析請求 catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse * response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } }
#### 2.3 文件上傳注意的問題:
1、爲保證服務器安全,上傳文件應該放在外界無法直接訪問的目錄下,比如放於WEB-INF目錄下。
2、爲防止文件覆蓋的現象發生,要爲上傳文件產生一個唯一的文件名。
3、如果上傳的目錄在Tomcat目錄中的wtpwebapps下的新建文件夾名爲upload ,如下:
則需要注意:
3.1. 如果修改代碼,則在tomcat重新啓動時 會被刪除
原因:當修改代碼的時候,tomcat會重新編譯一份新的class 並且重新部署(重新創建各種目錄)
3.2. 如果不修改代碼,則不會刪除
原因: 沒有修改代碼,class仍然是之前的class
因此, 爲了防止 上傳目錄丟失 : a. 虛擬路徑
b. 直接更換上傳目錄到 非tomcat目錄
4、限制上傳:限制類型、限制大小。注意 對文件的限制條件 寫在parseRequest之前
3、關於下載
下載:不需要依賴任何jar
a.請求(地址a form),請求Servlet
b.Servlet通過文件的地址 將文件轉爲輸入流 讀到Servlet中
c.通過輸出流 將 剛纔已經轉爲輸入流的文件 輸出給用戶
注意:下載文件 需要設置2個 響應頭:
response.addHeader("content-Type","application/octet-stream" );//MIME類型:二進制文件(任意文件) response.addHeader("content-Disposition","attachement;filename="+fileName );//fileName包含了文件後綴:abc.txt
文件下載代碼:
package org.student.servlet; import java.io.IOException; import java.io.InputStream; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet implementation class DownloadServlet */ public class DownloadServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public DownloadServlet() { super(); // TODO Auto-generated constructor stub } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); //獲取需要下載的文件名 String fileName = request.getParameter("filename") ;//form 、a href、 ...Server?a=b //下載文件:需要設置 消息頭 response.addHeader("content-Type","application/octet-stream" );//MIME類型:二進制文件(任意文件) response.addHeader("content-Disposition","attachement;filename="+fileName );//fileName包含了文件後綴:abc.txt //Servlet通過文件的地址 將文件轉爲輸入流 讀到Servlet中 InputStream in = getServletContext().getResourceAsStream("/res/MIME.png") ; //通過輸出流 將 剛纔已經轉爲輸入流的文件 輸出給用戶 ServletOutputStream out = response.getOutputStream() ; byte[] bs = new byte[10]; int len=-1 ; while( (len=in.read(bs)) != -1) { out.write(bs,0,len); } out.close(); in.close(); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } }
到這裏,到了最開心的時刻了!!!關於文件上傳下載的源碼與筆記已經打包好了QnQ:
鏈接:https://pan.baidu.com/s/1oyyEkctcvY3AvTsJNkiuuQ 提取碼:30e7