1. 程式人生 > >關於使用設定表單屬性enctype="multipart/form-data"之後傳值問題

關於使用設定表單屬性enctype="multipart/form-data"之後傳值問題

今天做一個簡單的商城專案的時候碰到了一個問題,將前臺頁面傳過來的引數直接想當然的使用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

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);
    }
}
service和dao就不貼了,實現功能就是向資料庫新增一個product實體