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
-->
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/