天天看點

Servlet 2.3過濾器程式設計(二) (轉)UploadTest

Servlet 2.3過濾器程式設計(二) (轉)[@more@]  servlet 2.3過濾器 程式設計(二)

 XML:namespace prefix = o ns = "urn:schemas-microsoft-com:Office:office" />

檔案上傳過濾器

我們将看到的最後一個過濾器是處理多路/多類型資料的POST請求,該類型的請求能包含檔案上傳。每個多路/多類型資料POST請求包含所有參數和檔案,使用一種servlet不能識别的特别的格式。曆史上Servlet開發者使用第三方類來處理上傳,例如在我的com.oreilly.servlet包中的MultipartRequest和MultipartParser類。這裡我們将看到一種使用MultipartFilter的新方法來是處理這種請求更容易。該過濾器基于com.oreilly.servlet包下的parsers建構并已經被內建到該包中(參見Javaworld.com/javaworld/jw-06-2001/jw-0622-filters_p.html#resources#resources">Resources)。

MultipartFilter工作與觀察輸入的請求,當它發現一個檔案上傳請求時(content type:multipart/form-data),過濾器使用一個知道如何分析這種特殊content type格式的特殊請求包來将請求對象進行包裝。servlet擷取此特殊請求包并通過标準的getParameter()方法來無縫地通路此multipart參數,因為這個wrapper中已經重新定義了這些方法的功能。此servelt能夠通過将requset轉換成wrapper類型并使用wrapper中附加的getFile()方法來處理檔案上傳。

過濾器代碼:

package com.oreilly.servlet;

import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;

public class MultipartFilter implements Filter {

  private FilterConfig config = null;

  private String dir = null;

  public void init(FilterConfig config) throws ServletException {

  this.config = config;

  // DeteRmine the UPLOAD directory.  First look for an uploadDir filter

  // init parameter.  Then look for the context tempdir.

  dir = config.getInitParameter("uploadDir");

  if (dir == null) {

  File tempdir = (File) config.getServletContext()

  .getAttribute("javax.servlet.context.tempdir");

  if (tempdir != null) {

  dir = tempdir.toString();

  }

  else {

  throw new ServletException(

  "MultipartFilter: No upload directory found: set an uploadDir " +

  "init parameter or ensure the javax.servlet.context.tempdir " +

  "directory is valid");

  }

  }

  }

  public void destroy() {

  config = null;

  }

  public void doFilter(ServletRequest request, ServletResponse response,

  FilterChain chain) throws IOException, ServletException {

  HttpServletRequest req = (HttpServletRequest) request;

  String type = req.getHeader("Content-Type");

  // If this is not a multipart/form-data request continue

  if (type == null || !type.startsWith("multipart/form-data")) {

  chain.doFilter(request, response);

  }

  else {

  MultipartWrapper multi = new MultipartWrapper(req, dir);

  chain.doFilter(multi, response);

  }

  }

}

init()方法确定檔案上傳的路徑。這是multipart parser放置檔案的地方,是以實際的請求并不需要駐留在記憶體中。它先查找uploadDir過濾器初始化參數,如果沒找到,則使用預設的tempdir目錄——Servlet api 2.2中的标準context屬性。

doFilter()方法檢查請求的content type,如果是multipart/form-data請求,則将此請求用MultipartWrapper打包。wrapper代碼如下:

package com.oreilly.servlet;

import java.io.*;

import java.util.*;

import javax.servlet.*;

import javax.servlet.http.*;

public class MultipartWrapper extends HttpServletRequestWrapper {

  MultipartRequest mreq = null;

  public MultipartWrapper(HttpServletRequest req, String dir)

  throws IOException {

  super(req);

  mreq = new MultipartRequest(req, dir);

  }

  // Methods to replace HSR methods

  public Enumeration getParameterNames() {

  return mreq.getParameterNames();

  }

  public String getParameter(String name) {

  return mreq.getParameter(name);

  }

  public String[] getParameterValues(String name) {

  return mreq.getParameterValues(name);

  }

  public Map getParameterMap() {

  Map map = new HashMap();

  Enumeration enum = getParameterNames();

  while (enum.hasMoreElements()) {

  String name = (String) enum.nextElement();

  map.put(name, mreq.getParameterValues(name));

  }

  return map;

  }

  // Methods only in MultipartRequest

  public Enumeration getFileNames() {

  return mreq.getFileNames();

  }

  public String getFilesystemName(String name) {

  return mreq.getFilesystemName(name);

  }

  public String getContentType(String name) {

  return mreq.getContentType(name);

  }

  public File getFile(String name) {

  return mreq.getFile(name);

  }

}

wrapper構造了一個com.oreilly.servlet.MultipartRequest對象以處理上傳分析并重載getParameter()方法族以使用MultipartRequest取代未加工的請求來讀取參數值。wrapper也定義了不同的getFile()方法以使一個servlet接收打包過的請求以能通過調用其他方法來處理上傳的檔案。

web.xml部署描述器用如下代碼來添加此過濾器:

  multipartFilter

  com.oreilly.servlet.MultipartFilter

  <!--

  uploadDir

  /tmp

  --&gt

ping>

  multipartFilter

  /*

  uploadTest

  UploadTest

   uploadTest

  /uploadTest

UploadText servlet如下:

import java.io.*;

import java.util.*;

import javax.servlet.*;

import javax.servlet.http.*;

import com.oreilly.servlet.*;

public class UploadTest extends HttpServlet {

  public void doPost(HttpServletRequest req, HttpServletResponse res)

  throws ServletException, IOException {

  res.setContentType("text/html");

  PrintWriter out = res.getWriter();

  out.println("");

  out.println("

UploadTest");

  out.println("

");

  out.println("

UploadTest

");

  // Parameters can now be read the same way for both

  // application/x-www-form-urlencoded and multipart/form-data requests!

  out.println("

Request Parameters:

");
      

  Enumeration enum = req.getParameterNames();

  while (enum.hasMoreElements()) {

  String name = (String) enum.nextElement();

  String values[] = req.getParameterValues(name);

  if (values != null) {

  for (int i = 0; i < values.length; i++) {

  out.println(name + " (" + i + "): " + values[i]);

  }

  }

  }

  out.println("

");

  // Files can be read if the request class is MultipartWrapper

  // Init params to MultipartWrapper control the upload handling

  if (req instanceof MultipartWrapper) {

  try {

  // Cast the request to a MultipartWrapper

  MultipartWrapper multi = (MultipartWrapper) req;

  // Show which files we received

  out.println("

Files:

");

  out.println("

");
      

  Enumeration files = multi.getFileNames();

  while (files.hasMoreElements()) {

  String name = (String)files.nextElement();

  String filename = multi.getFilesystemName(name);

  String type = multi.getContentType(name);

  File f = multi.getFile(name);

  out.println("name: " + name);

  out.println("filename: " + filename);

  out.println("type: " + type);

  if (f != null) {

  out.println("length: " + f.length());

  }

  out.println();

  }

  out.println("

");

  }

  catch (Exception e) {

  out.println("

");
      

  e.printStackTrace(out);

  out.println("

");

  }

  }

  out.println("");

  }

}

servlet的前一半顯示了過濾器如何将參數資料毫無改變的傳送給接收的servlet。後半部分則顯示了一個servlet是如何将請求向下傳送給MultipartWrapper以獲得附加的檔案通路方法。

一個驅動此servlet的HTML例子如下:

RM ACTION="uploadTest" ENCTYPE="multipart/form-data" METHOD=POST>

What is your name?

What is your age?

Which file do you want to upload?

Any other file to upload?

這是可能的輸出:

UploadTest

Request Parameters:

submitter (0): Jason

age (0): 28

Files:

name: file1

filename: 4008b21.tif

type: application/octet-stream

length: 39396

name: file2

filename: null

type: null

你們也許會疑惑我們如何确信由過濾器設定的MultipartWrapper能正确的傳送給接下來的servlet。在2号釋出稿規範和tomcat 4.0 beta 5中,那是不确定的。實際上,如果你試圖用/servlet/UploadTest去通路此servlet,你将注意到過濾并沒有正确工作,因為/servlet的調用将MultipartWrapper轉給Tomcat自己的特殊wrapper了。這允許參數能被正确解析,但檔案通路方法卻不能正确工作。在Servlet API專家組的讨論中,我們決定servlet容器不能對過濾器的wrapper做更多的包裝。這個servlet規範将被修改的更清楚。在Tomcat 4.0以後版本中将澄清這些規則。短期的辦法是在請求wrapper中使用getRequest()方法來“沿着”請求去找到這個隐藏的multipart wrapper。

從如下位址下載下傳該WAR檔案:

http://www.javaworld.com/jw-06-2001/Filters/mulitpart.war

過濾器能力

Servlet過濾器提供了一中強大的能力來控制請求的操作和響應的發生,提供新的servlet功能而不需要太多的代碼。我希望通過這些已經向你展示使用過濾器的可能情況,并教給你一些關于如何更有效的使用新的過濾器機能的技巧。

感謝這些過濾器的作者以及其他對過濾器提供有用建議的的人:Amy Roh,Criag McClanahan,Serge Knystautas,以及OpenSymphony成員。

關于作者

  見原文

資源

  見原文

file://請達人給指點斧正了,謝謝:)

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-982455/,如需轉載,請注明出處,否則将追究法律責任。

轉載于:http://blog.itpub.net/10748419/viewspace-982455/