我们用fileupload上传文件的时候,为了获取上传表单里的非文件表单域,通常都要不断去循环读取,每一个上传文件的方法都要重复同样的代码,很不方便,而struts2里面就把fileupload封装好了,可以很方便地用get()来获取表单里非文件域的值,那么底层是怎么实现的呢?
简单点来说,就是文件传达到servlet之前,先把上传的文件流用filter拦截过滤,在filter里面利用自己封装的文件流,再传送过去给filter,使得servlet里能够直接使用我们封装好的文件流,这样的话,就很方便,只需一个filter,以后哪个页面需要上传文件,只需要配置一些web.xml ,过滤一下就可以.
本文用到的是fileupload 1.2.现在一起看看实现的关键代码:
首先是要利用HttpServletRequestWrapper,实现一个自己的HttpServletRequest;
import java.util.Map;
import java.util.HashMap;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
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;
/**
*
* 拦截Servlet容器传给Servlet的请求信息
* 封装上传文件表单的请求信息
* @author Miss
*
*/
public class MultipartRequest extends HttpServletRequestWrapper {
HashMap<String,String[]> parameters = new HashMap<String,String[]>();
HashMap<String,FileItem> files = new HashMap<String,FileItem>();
public MultipartRequest(HttpServletRequest request)
throws FileUploadException, IOException {
super(request);
DiskFileItemFactory dff = new DiskFileItemFactory();
dff.setSizeThreshold(1024 * 1024); // 内存最多存储1MB数据,超过就用临时目录缓存
ServletFileUpload sfu = new ServletFileUpload(dff);
sfu.setSizeMax(1024 * 1024 * 10); // 最多上传10MB数据
sfu.setHeaderEncoding("utf-8");
List<FileItem> fileItems = null;
fileItems = sfu.parseRequest(request);
Iterator i = fileItems.iterator();
while (i.hasNext()) {
FileItem fi = (FileItem) i.next();
if (fi.isFormField()) {
String fieldName = fi.getFieldName();
String content = null;
content = fi.getString("utf-8");
setParameter(fieldName, content);
} else {
String pathSrc = fi.getName();
if (pathSrc.trim().equals("")) {
continue;
}
String fieldName = fi.getFieldName();
files.put(fieldName, fi);
}
}
}
private void setParameter(String fieldName, String content) {
String[] mValue = (String[]) parameters.get(fieldName);
if (mValue == null) {
mValue = new String[0];
}
String[] newValue = new String[mValue.length + 1];
System.arraycopy(mValue, 0, newValue, 0, mValue.length);
newValue[mValue.length] = content;
parameters.put(fieldName, newValue);
}
public String getParameter(String fieldName) {
String[] mValue = (String[]) parameters.get(fieldName);
if ((mValue != null) && (mValue.length > 0)) {
return mValue[0];
}
return null;
}
public Enumeration getParameterNames() {
Collection c = parameters.keySet();
return Collections.enumeration(c);
}
public String[] getParameterValues(String fieldName) {
String[] mValue = (String[]) parameters.get(fieldName);
return mValue;
}
public Map getParameterMap() {
return parameters;
}
public FileItem getFileItem(String fieldName) {
FileItem fItem = (FileItem) files.get(fieldName);
return fItem;
}
public Enumeration getFileItemNames() {
Collection c = files.keySet();
return Collections.enumeration(c);
}
}
接下来是写个filter来掉包一下上传的文件流
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
public class UploadFilter implements Filter {
public void destroy() {
// TODO Auto-generated method stub
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
String type = req.getHeader("Content-Type");
if (type == null || !type.startsWith("multipart/form-data")) {
chain.doFilter(request, response);
} else {
MultipartRequest mreq = null;
try {
mreq = new MultipartRequest(req);
} catch (Exception e) {
throw new ServletException(e);
}
chain.doFilter(mreq, response);
}
}
public void init(FilterConfig arg0) throws ServletException {
}
}
然后在需要实现上传的servlet里就能轻松获取上传表单里的值,就是平时的requset.getParameter().
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
public class UploadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setContentType("text/html;charset=gb2312");
PrintWriter out = resp.getWriter();
out.println("用户:" + req.getParameter("user"));
// 设置上传文件后的保存目录
String path = this.getServletContext().getRealPath("/upload");
File saveDir = new File(path);
if (!saveDir.exists()) {
if (!saveDir.mkdir()) {
out.println("无法创建储存目录");
return;
}
}
MultipartRequest mreq = (MultipartRequest) req;
Enumeration fileItemNames = mreq.getFileItemNames();
while (fileItemNames.hasMoreElements()) {
String name = (String) fileItemNames.nextElement();
FileItem fi = (FileItem) mreq.getFileItem(name);
String fileName = fi.getName().substring(
fi.getName().lastIndexOf("\\") + 1);
try {
fi.write(new File(saveDir, fileName));
out.println("上传文件成功!");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
这里是上传表单里有一个name=user 的非文件表单项,可以直接在servlet里用req.getParameter("user")获取.
分享到:
相关推荐
FileUpload不负责这部分操作,需要开发者实现。 10. **与其他框架集成**: - Commons FileUpload可与其他Java Web框架如Spring MVC、Struts等集成,提供统一的文件上传处理方式。 总的来说,Apache Commons ...
"fileuoload包"很可能是对Apache Commons FileUpload库的一个引用,这是一个非常实用的工具,专门处理HTTP请求中的多部分数据,例如文件上传。Apache Commons FileUpload库简化了从请求中解析并处理文件上传的过程。...
Apache Commons FileUpload库提供了一些接口和类来支持这些功能,但具体实现还需要根据应用的需求来编写。 总的来说,Apache Commons FileUpload和Apache Commons IO是Java Web开发中处理文件上传下载的重要工具,...
### ASP.NET 文件上传控件详解及实践技巧 #### 一、解决文件上传大小限制问题 在ASP.NET开发中,文件上传是一项常见的需求。然而,在实际应用中,经常会遇到上传文件大小受到限制的情况。默认情况下,ASP.NET框架...
commons-fileupload-1.4.jar