文件上傳
1.1文件上傳概述
就是將客戶端的數據發送到服務器上的操作
1.2文件上傳要求
1.2.1瀏覽器端要求(通用瀏覽器的要求)
-
表單提交方式 post
-
提供文件上傳框(組件) input type="file"
-
表單的entype屬性必須為
multipart/form-data
1.2.2服務器端要求
要使用request.getInputStream()來獲取數據.
注意:
若表單使用了 multipart/form-data ,使用原生request.getParameter()去獲取參數的時候都為null
1.3常見的文件上傳框架
commons-fileupload
struts2(底層:commons-fileupload)
serlvet3.0
...
1.4commons-fileupload的使用
apache出品的一款專門處理文件上傳的工具類
使用步驟:
-
導入jar包
-
創建磁盤文件項工廠
DiskFileItemFactory factory=new DiskFileItemFactory();
-
創建核心上傳對象
ServletFileUpload upload=new ServletFileUpload(factory); -
解析請求,獲取所有的上傳組件 List<FileItem>
List<FileItem> list=upload.parseRequest(request); -
遍歷list 獲取每一個上傳項
FileItem的API:
getFiledName():獲取標簽里面name屬性的值
isFormFiled():判斷是否是普通上傳組件;
true:普通上傳組件,不是File text,password,hidden....
false:文件上傳組件 是File <input type="file">
-
普通上傳組件, 不是File
getString("utf-8"):獲取(普通上傳組件)用戶輸入的內容
-
文件上傳組件 是File
getName():獲取文件名稱
getInputStream():獲取文件的流(文件內容)
delete():刪除文件上傳時候產生的臨時文件
Eg:
1 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 2 3 try { 4 //創建磁盤文件項工廠 5 DiskFileItemFactory factory = new DiskFileItemFactory(); 6 //創建核心上傳對象 7 ServletFileUpload fileUpload = new ServletFileUpload(factory); 8 //獲得所有的上傳組件 9 List<FileItem> list = fileUpload.parseRequest(request); 10 for (FileItem fileItem : list) { 11 //獲得標簽的name屬性值 12 System.out.println(fileItem.getFieldName()); 13 //判斷是否是文件上傳 14 if(fileItem.isFormField()){ 15 //普通上傳組件 16 //獲得普通上傳組件的內容 17 System.out.println(fileItem.getString("utf-8")); 18 19 }else{ 20 //文件上傳組件 21 //獲得文件上傳組件的輸入流 22 InputStream is = fileItem.getInputStream(); 23 24 //創建文件輸出流 25 OutputStream os= new FileOutputStream("G:/1.txt"); 26 27 IOUtils.copy(is, os); 28 29 os.close(); 30 } 31 32 } 33 34 } catch (Exception e) { 35 e.printStackTrace(); 36 } 37 }
1.5上傳注意問題
-
文件重名問題
給文件取一個隨機名稱, uuid方式 或者 毫秒值++三個隨機數
-
文件名稱問題 目的是獲得文件真實名字,不帶盤符的
如果是IE:文件名帶盤符E:/data/Desktop/a.txt
其它的火狐,谷歌是文件本來的名字: a.txt
瀏覽器不同,有可能獲取的名稱不同(IE是帶盤符的), 1.txt 或者 G:\1.txt
-
常見的目錄分離
按用戶划分
按時間划分
按數量划分
隨機划分 算法:
1 /** 2 * 獲取文件目錄,可以獲取256個隨機目錄 3 * @return 隨機目錄 /a/c 4 */ 5 public static String getDir(){ 6 String s="0123456789ABCDEF";//16個 7 Random r = new Random(); 8 return "/"+s.charAt(r.nextInt(16))+"/"+s.charAt(r.nextInt(16)); 9 }
-
三,思路分析
-
在left.jsp上添加一個連接,"添加商品",點擊,在主頁面上打開一個表單頁面
.../adminProductServlet?method=addUI
-
創建addUI()方法
調用業務,獲得所有的分類List
把List存到request,轉發到 /admin/product/add.jsp
-
在add.jsp頁面,點擊確定按鈕,把數據提交到服務器
//請求的Servlet還能繼承BaseServlet??? 不可以 因為BaseServlet依賴requet.getParamet("method")獲得方法名
<form action="${pageContext.request.contextPath}/addProductServlet" method="post" enctype="multipart/form-data">
//把每一個表單子標簽設置name屬性
</form> -
創建AddProductServlet ,在doGet()方法里面:
//封裝成Product, 調用業務,最終保存到數據庫
//保存圖片文件到服務器
-
創建Service
-
創建Dao
四,代碼實現
-
WEB層(AddProductServlet)
1 public class AddProductServlet extends HttpServlet { 2 private static final long serialVersionUID = 1L; 3 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 4 try { 5 //1.創建磁盤文件項工廠 6 DiskFileItemFactory factory = new DiskFileItemFactory(); 7 //2.創建核心上傳對象 8 ServletFileUpload upload = new ServletFileUpload(factory); 9 //3.解析請求,獲得文件項集合 10 List<FileItem> list = upload.parseRequest(request); 11 12 Map<String, String> map = new HashMap<String,String>(); 13 //4.遍歷文件項集合 14 for (FileItem fileItem : list) { 15 //4.1獲得表單里面name的值,(name的值應該和javaBean的屬性是一致) 16 String fieldName = fileItem.getFieldName(); 17 //4.2 判斷是否是file 18 if(fileItem.isFormField()){ 19 //不是file 20 //a.獲得value的值 21 String value = fileItem.getString("utf-8"); 22 map.put(fieldName, value); 23 24 }else{ 25 //是file 26 //a.獲得文件名 27 String fileName = fileItem.getName(); 28 //b.獲得真實的文件名 29 fileName = UploadUtils.getRealName(fileName); 30 //c.獲得隨機文件名 31 String uuidName = UploadUtils.getUUIDName(fileName); 32 //d.獲得一個隨機目錄名 /a/b/c 33 String dir = UploadUtils.getDir(); 34 //e.存到map里面 products/1/c_0001.jpg 35 map.put(fieldName, "products"+dir+"/"+uuidName); 36 //f:把文件保存在服務器 37 String realPath = getServletContext().getRealPath("/products"); 38 File fileDir = new File(realPath, dir); 39 if(!fileDir.exists()){ 40 fileDir.mkdirs(); 41 } 42 43 OutputStream os = new FileOutputStream(new File(fileDir, uuidName)); 44 //獲得輸入流 45 InputStream is = fileItem.getInputStream(); 46 IOUtils.copy(is, os); 47 //刪除臨時文件 48 fileItem.delete(); 49 //關閉流 50 IOUtils.closeQuietly(is); 51 IOUtils.closeQuietly(os); 52 } 53 } 54 55 //5.封裝product對象 56 Product product = new Product(); 57 //5.1 使用beanutils封裝 58 BeanUtils.populate(product, map); 59 //5.2手動封裝pid,pdate,pflag 60 product.setPid(UUIDUtils.getId()); 61 product.setPdate(new Date()); 62 product.setPflag(Constant.PRODUCT_IS_UP); 63 //5.3手動設置 category 64 Category c = new Category(); 65 c.setCid((String)map.get("cid")); 66 product.setCategory(c); 67 68 ProductService productService = (ProductService) BeanFactory.getBean("ProductService"); 69 System.out.println(product.toString()); 70 71 productService.save(product); 72 73 response.sendRedirect(request.getContextPath()+"/adminProductServlet?method=findAll"); 74 75 } catch (Exception e) { 76 e.printStackTrace(); 77 } 78 } 79 80 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 81 doGet(request, response); 82 } 83 84 }
快捷鍵:
-
快速查找頁面或者Java類
-
查看繼承關系
-
查看當前類的結構(方法)
封裝:
-
WEB(Servlet): 表單里面/前端頁面獲得數據比較多,通常在WEB層封裝,傳給Service
-
Dao: 是從數據庫獲得, 通過只封裝和數據庫語句對應的數據(JavaBean,List), 傳給Service
-
Service: 補充WEB層傳過來的,傳給Dao; 補充Dao 傳過來的,傳給WEB (eg:PageBean)
-
JavaBean: 如果當前javaBean需要封裝邏輯,定義方法; 通常的話是一張表對應一個JavaBean
---恢復內容結束---