Servlet基於HttpServletRequestWrapper的檔案上傳

來源:互聯網
上載者:User

標籤:

在使用servlet上傳的時候,因為request裡面有時候既包含了參數資訊還有檔案資訊,取出來的時候就會很麻煩,所以我們可以根據request取出參數的原理,相當於自訂一個request來實現我們的檔案上傳和其他參數取出的分離.

一.關聯關係和依賴關係

介紹這個問題之前,需要先理解幾個概念

  • 關聯關係

    用下面簡單代碼解釋,也就是A裡麵包含一個B的執行個體

Class A{    private B b;}
  • 依靠關係

用下面代碼解釋就是A中的方法需要B類的作為參數參與

Class A{    public void f(B b);}

說到這就想起了裝飾者模式,兩者都可以說是裝飾者模式的一種實現吧.下面要做的也是利用裝飾者模式來解決.

二.具體實現1.HttpServletRequest

從類的結構圖,可以看出來HttpServletRequest實現了兩個介面,這裡我們重點看HttpServletRequestWrapper.

尋找API會發現HttpServletRequestWrapper裡面管理著HttpServletRequest裡面鎖調用的方法,因此我們只要自訂一個類,繼承HttpServletRequestWrapper,然後利用自訂的類來建立req就可以實現自訂的request了.

2.自訂MultipartRequestWrapper

自訂前需要引入兩個上傳組件包

自訂前需要注意:上傳資料可能有多值現象,比如checkbox,這樣的就是一個數組.另外之前的檔案上傳使用的是傳統的方法traditional API,這裡換成Streaming API,相比傳統的方式,這種方式更加迅速.

import org.apache.commons.fileupload.FileItemIterator;import org.apache.commons.fileupload.FileItemStream;import org.apache.commons.fileupload.FileUploadException;import org.apache.commons.fileupload.servlet.ServletFileUpload;import org.apache.commons.fileupload.util.Streams;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletRequestWrapper;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.util.Arrays;import java.util.HashMap;import java.util.Map;/** * Created by nl101 on 2016/3/8. */public class MultipartRequestWrapper extends HttpServletRequestWrapper {    //儲存參數的集合    private Map<String,String[]> params = new HashMap<>();    private static String PATH = "E:\\temp\\"; //設定上傳路徑    public MultipartRequestWrapper(HttpServletRequest request) {        super(request);        setParams(request);//對request進行解析,並存入map中    }    /**     * 通過StreamingAPI的方式上傳檔案     */    private void setParams(HttpServletRequest request){        //擷取上傳檔案類型        if (ServletFileUpload.isMultipartContent(request)){            //建立ServletFileUpload執行個體            ServletFileUpload fileUpload = new ServletFileUpload();            try {                //解析request請求 返回FileItemStream的iterator執行個體                FileItemIterator iter = fileUpload.getItemIterator(request);                InputStream is = null;//輸出資料流                //迭代取出                while (iter.hasNext()){                    FileItemStream item = iter.next();//擷取檔案流                    String name = item.getFieldName();//返回表單中標籤的name值                    is = item.openStream();//得到對應表單的輸出資料流                    if (item.isFormField()){//如果是非檔案域,設定進入map,這裡要注意多值處理                        setFormParam(name,is);//如果不是檔案上傳,處理                    }else {                        if (is.available()>0){//如果輸出資料流的內容大於0                            String fname = item.getName();//擷取檔案名稱                            Streams.copy(is,new FileOutputStream(PATH+fname),true);//拷貝內容到上傳路徑                            params.put(name,new String[]{fname});//把檔案名稱設定進request中                        }                    }                }            } catch (FileUploadException e) {                e.printStackTrace();            } catch (IOException e) {                e.printStackTrace();            }        }else {            params = request.getParameterMap();//如果不是檔案上傳請求,則直接設定map        }    }    /**     * 處理非上傳的表單     * @param name     * @param is     */    private void setFormParam(String name, InputStream is) {        try {            if (params.containsKey(name)){//判斷當前值name是否已經儲存過                String[] values = params.get(name);//取出已經儲存過的值                values = Arrays.copyOf(values,values.length+1);//把當前數組擴大                values[values.length-1] = Streams.asString(is);//增加新值                params.put(name,values);//重新添加到map中            }else {                params.put(name,new String[]{Streams.asString(is)});//直接存入參數中            }        } catch (IOException e) {            e.printStackTrace();        }    }    /**     * 返回參數map集合,自訂後上傳檔案,上傳成功則返迴文件名     * @return     */    @Override    public Map<String,String[]> getParameterMap() {        return params;    }    /**     * 從請求中取出參數     * @param name     * @return     */    @Override    public String getParameter(String name) {        String[] values = params.get(name);        if(values!=null) {            return values[0];        }        return null;    }    /**     * 從請求中取出多個參數值,如checkbox的值     * @param name     * @return     */    @Override    public String[] getParameterValues(String name) {        String[] values = params.get(name);        if(values!=null) {            return values;        }        return null;    }}
3.使用自訂的request

使用就很簡單了,直接在處理上傳的Servlet中來再次封裝下req即可

import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;/** * Created by nl101 on 2016/3/9. */public class UploadServlet extends HttpServlet {    @Override    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {        req = new MultipartRequestWrapper(req);//重新封裝        req.getParameter("username");//接著就可以像往常一樣處理請求了        req.getParameter("file");//接著就可以像往常一樣處理請求了    }}

別忘記配置WEB.xml檔案

<servlet>        <servlet-name>UploadServlet</servlet-name>        <servlet-class>com.servlet.UploadServlet</servlet-class>    </servlet>    <servlet-mapping>        <servlet-name>UploadServlet</servlet-name>        <url-pattern>/upload.do</url-pattern>    </servlet-mapping>
4,jsp測試
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html>  <head>    <title>上傳測試</title>  </head>  <body>    <form action="upload.do" method="post" enctype="multipart/form-data">        <table border="1">          <tr>            <td>使用者名稱:<input name="username" type="text"></td>          </tr>          <tr>            <td>上傳:<input type="file" name="file"></td>          </tr>          <tr>            <td><input type="submit" value="上傳"></td>          </tr>        </table>    </form>  </body></html>

這樣點擊上傳,就可以完成上傳了,而且我們的處理還是像往常一樣通過req.getParameter(“username”),這樣用起來省心太多了.

Servlet基於HttpServletRequestWrapper的檔案上傳

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.