關於使用設定表單屬性enctype="multipart/form-data"之後傳值問題
阿新 • • 發佈:2019-02-16
今天做一個簡單的商城專案的時候碰到了一個問題,將前臺頁面傳過來的引數直接想當然的使用BeanUtils的populate封裝進了bean,去資料庫看發現只有自己給bean設定的值,前臺傳的一個都沒有儲存進去.查了資料發現,使用了multipart/form-data之後,表單資料都是二進位制傳輸的,request不能識別到,那麼只能使用fileitem的isFormFiled方法判斷是表單中的資料之後,取出fieldname屬性名.還有getString得到屬性值.封裝進自己建立的map裡面.再使用BeanUtils進行封裝.貼上程式碼.
addProduct.jsp
<%@page contentType="text/html; UTF-8" language="java" pageEncoding="UTF-8" %> <html> <head> <title>新增商品</title> <link rel="stylesheet" href="css/style.css" type="text/css" media="screen"/> <style type="text/css"> .main { text-align: center; border-radius: 20px; width: 300px; height: 400px; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); } td { white-space: nowrap; } </style> </head> <body> <div class="main"> <form action="${pageContext.request.contentType}/addProduct" method="post" enctype="multipart/form-data"> <table> <tr> <td>商品名稱</td> <td><input type="text" name="name"/></td> </tr> <tr> <td>商品價格</td> <td><input type="text" name="price"/></td> </tr> <tr> <td>商品類別</td> <td> <select name="category"> <option>請選擇</option> <option value="圖書音像">圖書音像</option> <option value="家用電器">家用電器</option> <option value="服裝衣帽">服裝衣帽</option> </select> </td> </tr> <tr> <td>商品數量</td> <td><input type="text" name="amount"/></td> </tr> <tr> <td>商品圖片</td> <td><input type="file" name="file"/></td> </tr> <tr> <td>商品描述</td> <td> <textarea name="description" cols="20" rows="10"></textarea> </td> </tr> <tr> <td colspan="2"> <input type="submit" value="提交"/> <input type="reset" value="重置"/> <input type="button" value="取消" id="cancel"/> </td> </tr> </table> </form> </div> </body> <script type="text/javascript"> var cancel = document.getElementById("cancel"); cancel.onclick = function () { window.location = "${pageContext.request.contentType}/"; } </script> </html>
AddProductServlet.java
package com.relic.eStore.web; import com.relic.eStore.domain.Product; import com.relic.eStore.exception.ProductException; import com.relic.eStore.service.ProductService; import com.relic.eStore.utils.UUIDUtils; import com.relic.eStore.utils.UploadUtils; import org.apache.commons.beanutils.BeanUtils; 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; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import java.util.List; import java.util.Map; public class AddProductServlet extends HttpServlet { protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //建立一個map儲存屬性名和屬性值 Map<String, String[]> info = new HashMap<>(); //處理前臺的圖片上傳操作 DiskFileItemFactory factory = new DiskFileItemFactory(); //設定快取路徑 factory.setRepository(new File(req.getServletContext().getRealPath("/upload/tmp"))); ServletFileUpload upload = new ServletFileUpload(factory); //解決檔名包含中文亂碼問題 upload.setHeaderEncoding("UTF-8"); try { List<FileItem> fileItems = upload.parseRequest(req); Product product = new Product(); info.put("id", new String[]{UUIDUtils.getUUID()}); //根據item是否是上傳元件,進行上傳操作 for (FileItem fileItem : fileItems) { if (fileItem.isFormField()) { info.put(fileItem.getFieldName(), new String[]{fileItem.getString("UTF-8")}); } else { //獲取檔名稱 String filename = UploadUtils.getFilename(fileItem.getName()); //獲取隨機的檔名 String uuidName = UploadUtils.getUuidName(filename); //根據檔名得到2級目錄 String _directory = UploadUtils.getRandomDir(uuidName); //得到真實路徑 File directory = new File(req.getServletContext().getRealPath("/upload" + _directory)); if (!directory.exists()) { directory.mkdirs(); } File file = new File(directory, uuidName); //完成上傳操作 IOUtils.copy(fileItem.getInputStream(), new FileOutputStream(file)); //刪除臨時檔案 fileItem.delete(); //將路徑封裝 info.put("imgUrl", new String[]{file.getAbsolutePath()}); } } //將info中儲存的資訊封裝進bean BeanUtils.populate(product, info); //呼叫service方法,儲存product資訊 ProductService service = new ProductService(); service.addProduct(product); resp.sendRedirect(req.getContextPath() + "/index.jsp"); return; } catch (IllegalAccessException | FileUploadException | InvocationTargetException | ProductException e) { e.printStackTrace(); } } protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
UploadUtils.java
service和dao就不貼了,實現功能就是向資料庫新增一個product實體package com.relic.eStore.utils; public class UploadUtils { //根據fileItem得到的檔名得到只包含名稱和檔案格式的檔名 public static String getFilename(String name) { int index = name.indexOf("//"); if (index == -1) { return name; } return name.substring(index + 1); } //根據檔名的hashcode生成2級目錄 public static String getRandomDir(String filename) { int hashcode = filename.hashCode(); //1級目錄 int d1 = hashcode & 0xf; //2級目錄 int d2 = (hashcode >> 4) & 0xf; return "/" + d1 + "/" + d2; } //返回隨機的uuid+檔案格式的檔名 public static String getUuidName(String filename) { String uuid = UUIDUtils.getUUID(); int index = filename.indexOf("."); if (index == -1) { return uuid; } return uuid + filename.substring(index); } }