文件上傳:html
1.所須要的包:前端
commons-fileupload-1.2.1.jarjava
commons-io-1.4.jarweb
2.瀏覽器端:數據庫
1>.請求方式必須是 postapache
2>.須要使用組件<input type="file" name="f">瀏覽器
3>.表單必須設置encType="multipart/form-data"安全
4>.上傳文件的input 中,name屬性必需要填寫,否則不會上傳. 服務器
<form action="${pageContext.request.contextPath}/upload2" method="post" enctype="multipart/form-data"> <input type="file" name="f"> <input type="submit" value="上傳"> <form/>
3.服務器端:app
能夠經過request對象,獲取InputStream,能夠將瀏覽器提交的全部請求正文讀取到。
4.核心類的使用:
1.DiskFileItemFactory 用於設置文件上傳時,緩衝區大小以及臨時文件存儲位置.
1 能夠設置文件上傳緩衝區大小
factory.setSizeThreshold(1024*1024); //設置爲1m 默認是10k
2能夠設置臨時文件存儲位置
File temp=new File(this.getServletContext().getRealPath("/temp"));
factory.setRepository(temp); //能夠指定臨時文件存儲位置,默認是系統的臨時文件存儲位置
2.ServletFileUpload 它的做用是真正完成解析數據操做上傳類
1.pareRequest(HttpServletRequest request)
獲得全部的上傳信息,將每一部分映射成FileItem對象.
2.isMultipartContent(HttpServletRequest request)
這個方法返回值是boolean,它是用於判斷當前表單是不是一個上傳的表單,
簡單說,就判斷它的encType的值是不是 multipart/form-data.
3.setHeaderEncoding(String encoding)
用於解決上傳文件名稱中文亂碼問題
4.能夠設置上傳文件大小,若是超過設置大小.將會拋出異常(默認沒有最大值)
void setFileSizeMax(long fileSizeMax) 設置單個文件上傳大小
void setSizeMax(long sizeMax) 設置總文件上傳大小
3.FileItem 它表明的是每個上傳項(其時就是表單中的每個組件)
1.isFormField()
這個方法返回的是boolean類型,
它是判斷當前組件是不是上傳組件 簡單說,就是判斷type="file",
若是返回true,表明不是上傳組件,返回false,表明是上傳組件
2.getName()
獲取非上傳組件的上傳文件的名稱,若是是非上傳組件,返回的是null
3.getFieldName()
獲取組件名稱,提交的鍵
4.getString()
獲取非上傳組件的value值,
經過它也能夠獲取上傳的文件內容,可是,使用它獲取不合適。
若是使用了commons-fileupload進行文件上傳,而上傳表單中包含了
非上傳組件,獲取其值,不能使用request獲取.
getString()有一個重載的方法 getString(String encoding)能夠解決亂碼問題
問題:使用getString()去獲取上傳文件內容不合適,那麼怎樣操做?
基本操做:
經過FileItem.getInputStream();能夠獲取一個輸入流,這個輸入流就能夠讀取出上傳文件內容。
InputStream is = item.getInputStream(); // 用於讀取上傳文件內容的輸入流.
FileOutputStream fos = new FileOutputStream(
"d:/upload/" + filename);
int len = -1;
byte[] b = new byte[1024 * 10];
while ((len = is.read(b)) != -1) {
fos.write(b, 0, len);
fos.flush();
}
fos.close();
is.close();
能夠使用IOUtils工具完成文件copy操做
IOUtils.copy(is, fos);
5.delete方法
它是用於上傳完成後,刪除臨時文件的
4.注意問題:
1>關於文件上傳時文件名稱包含中文的亂碼問題?
調用ServletFileUpload的setHeaderEncoding方法解決
2>普通表單字段提交時,中文亂碼問題?
FileItem的 getString方法返回提交的值.經過參數來設置解碼碼錶
例如: getString("UTF-8");
3>如何設置上傳文件大小限制?
調用ServletFileUpload的setSizeMax(總大小)
setFileSizeMax(每一個大小)方法
4>上傳文件後,咱們應該把文件保存到什麼位置?
1.上傳以後,客戶端直接可以訪問到的地方. WEBRoot下
2.上傳後其餘用戶不能直接訪問
放到webRoot之外的文件夾. WEB-INF(安全目錄)下或硬盤其餘位置 .例如 d:/xxx
5>上傳文件時,該使用什麼名字將文件保存?
文件名稱不能使用用戶命名的名稱.
用戶命名的名稱咱們須要保存到數據庫中,在下載時使用.
6>不是用用戶命名的名稱,咱們以什麼名稱保存文件(不能重複)?
UUID
登陸用戶名+當前系統毫秒數 (只容許單文件上傳,一個請求只能上傳一個文件)
7>如何得到用戶命名的文件名?
getName方法便可得到文件名.
IE瀏覽器中,會把文件的在客戶端的完整路徑傳過來.須要截取.
其餘瀏覽器只會文件名稱傳過來.直接使用,無需截取.
8>爲了防止同一個目錄下方上傳文件數量過多,思考如何解決?
/upload/2016/03/27/xxxx 使用當前日期做爲子文件夾名稱
當前登陸用戶的用戶名做爲文件夾名稱(不推薦)
實例:
upload.jsp(前端僅貼出相關提交的代碼)
<!-- 1. 表單必須是post提交. 2. 修改enctype屬性 . EncodeType 請求正文內容類型. application/x-www-form-urlencoded (默認值:用於提交文本類型內容). multipart/form-data (多段式提交) 3. 文件上傳時,需使用 input type=file 組件 注意: 該組件必定要設置name屬性. --> <body> <form action="/upload/AServlet" method="post" enctype="multipart/form-data"> 用戶名:<input type="text" name="username"/><br/> <input type="file" name="file1" /><br/> <input type="file" name="file2"/> <input type="submit" value="提交"> </form> </body>
2.Aservlet.jsp
package cn.test.upload; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.UUID; 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.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.io.IOUtils; public class AServlet extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.建立解析器配置工廠 //DiskFileItemFactory:用於設置文件上傳時,緩衝區的大小以及臨時文件的存儲位置 DiskFileItemFactory factory = new DiskFileItemFactory(); //2.根據配置工廠的配置建立解析器類 //ServletFileUpload:真正完成解析上傳數據的操做類 ServletFileUpload upload = new ServletFileUpload(factory); //3.判斷是否爲多段式方式提交,也就是判斷它的encType的值是不是 multipart/form-data if(!upload.isMultipartContent(request)){ throw new RuntimeException("您的表單提交方式錯誤"); } //設置多段式每一段段頭的編碼表 upload.setHeaderEncoding("UTF-8"); //FileItem:表明的就是每個上傳項,其實就是表單中的每個組件 List<FileItem> list=null; //3.調用解析方法,解析request對象 try { list = upload.parseRequest(request); }catch (FileUploadException e) { e.printStackTrace(); throw new RuntimeException("解析request對象失敗!"); } if(list!=null){ for(FileItem item:list){ //判斷item爲普通文本提交段 if(item.isFormField()){ //得到普通文本提交的鍵 String key = item.getFieldName(); //得到普通文本提交的值,使用item.getString()的重載方法,解決中文亂碼問題 String value = item.getString("UTF-8"); System.out.println(key+":"+value); } //處理文件上傳段 else{ //獲取上傳的文件名 //String name = item.getName(); //System.out.println(name); InputStream is = item.getInputStream(); //將文件保存到upload目錄下(文件名稱不能重複,不能存儲在單一文件夾下) //生成uuid文件名稱 String uuid = UUID.randomUUID().toString(); //使用日期進行分目錄 //得到upload目錄所在的絕對路徑 String dirPath = getServletContext().getRealPath("/upload"); //根據當前時間,得到時間路徑 Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("/yyyy/MM/dd/"); String datePath = sdf.format(date); //檢查當前時間目錄結構是否存在,若是不存在則建立 File file = new File(dirPath+datePath); if(!file.exists()){ file.mkdirs(); } // InputStream in = item.getInputStream(); FileOutputStream out = new FileOutputStream(dirPath+datePath+uuid); IOUtils.copy(in, out); //釋放資源,刪除臨時文件 out.close(); in.close(); item.delete(); } } } } }
文件下載
1.文件下載方式
1> 直接將待下載文件放到webRoot文件夾或子文件夾下.
2>須要控制資源的下載.在下載前要通過邏輯處理.
將資源放到用戶不能直接訪問的地方. 例如: WEB-INF 或 d:/upload
2.下載文件名稱中文亂碼問題
response.setHeader("content-disposition", "attachment;filename="+ filename);
這段代碼中的filename是指定下載文件時的名稱
對於IE瀏覽器,它要求必須給一個UTF-8碼
對於firefox瀏覽器,它要求必須給一個base64編碼
if (agent.contains("MSIE")) { // IE瀏覽器 filename = URLEncoder.encode(filename, "utf-8"); filename = filename.replace("+", " "); } else if (agent.contains("Firefox")) { // 火狐瀏覽器 BASE64Encoder base64Encoder = new BASE64Encoder(); filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?="; } else { // 其它瀏覽器 filename = URLEncoder.encode(filename, "utf-8"); }
文件下載實例:
1.DownLoadServlet.java
import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.io.IOUtils; public class DownloadServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.得到請求的文件名 String fileName = request.getParameter("name"); fileName = new String(fileName.getBytes("ISO-8859-1"),"UTF-8"); //2.設置content-type頭|content-disposition頭 response.setContentType(getServletContext().getMimeType(fileName)); response.setHeader("content-disposition","attachment;filename="+DownloadUtils.encode(fileName, request)); //3.根據參數指定的文件,找到對應的文件資源流 InputStream is = getServletContext().getResourceAsStream("/WEB-INF/"+fileName); //4.得到向瀏覽器輸出的流 ServletOutputStream os = response.getOutputStream(); //5.將兩個流對接 IOUtils.copy(is, os); //6.關閉資源 is.close(); os.close(); } }
2.DownLoadUtils.java
import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import javax.servlet.http.HttpServletRequest; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; public class DownloadUtils { public static String encode(String fileName,HttpServletRequest request){ //1.得到瀏覽器的類別 String agent = request.getHeader("User-Agent"); //2.判斷瀏覽器類型 if(agent.contains("Firefox")){ //火狐瀏覽器=>按照base64進行編碼 BASE64Encoder base64Encoder = new BASE64Encoder(); try { fileName = "=?utf-8?B?" + base64Encoder.encode(fileName.getBytes("utf-8")) + "?="; } catch (UnsupportedEncodingException e) { e.printStackTrace(); } }else{ //非火狐瀏覽器=>按照urlencoded編碼方式編碼 try { fileName = URLEncoder.encode(fileName,"UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } //3.返回編碼後的結果 return fileName; } }
3.download.jsp
<body> <a href="/download/DownloadServlet?name=top.csv">下載top.csv文件</a><br/> <a href="/download/DownloadServlet?name=走遍中國.JPG">下載圖片_走遍中國</a><br/> <a href="/download/DownloadServlet?name=原點.mp3">下載原點.mp3</a> </body>