最近遇到一个文件上传的项目,而且在这个项目中遇到的文件上传的次数还是挺多的,所以就写了个Filter过滤器。这一个想法还是从一本书上看到的,所以原则上说并不是在下原创。不过因为补充了一点东西,所以,嘿嘿,不说了。


首先需要写个Filter:

packageyin.filter;importjava.io.File;importjava.io.FileOutputStream;importjava.io.IOException;importjava.io.OutputStream;importjava.util.HashMap;importjava.util.Iterator;importjava.util.List;importjava.util.Map;importjavax.servlet.Filter;importjavax.servlet.FilterChain;importjavax.servlet.FilterConfig;importjavax.servlet.ServletException;importjavax.servlet.ServletRequest;importjavax.servlet.ServletResponse;importjavax.servlet.annotation.MultipartConfig;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletRequestWrapper;importorg.apache.commons.fileupload.DiskFileUpload;importorg.apache.commons.fileupload.FileItem;publicclassUploadfilterimplementsFilter{privateStringencoding;@Overridepublicvoiddestroy(){}@OverridepublicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException,ServletException{UploadRequestWrapperuploadRequestWrapper=newUploadRequestWrapper((HttpServletRequest)request);chain.doFilter(uploadRequestWrapper,response);}@Overridepublicvoidinit(FilterConfigconfig)throwsServletException{encoding=config.getServletContext().getInitParameter("encoding");if(encoding==null){encoding="utf-8";}}classUploadRequestWrapperextendsHttpServletRequestWrapper{//文件头类型privatestaticfinalStringMULTIPART_HEADER="Content-type";//是否是上传文件privatebooleanmultipart;//保存提交的数据privateMap<String,Object>params=newHashMap<String,Object>();@SuppressWarnings("deprecation")publicUploadRequestWrapper(HttpServletRequestrequest){super(request);//判断是否是上传文件multipart=request.getHeader(MULTIPART_HEADER)!=null&&request.getHeader(MULTIPART_HEADER).startsWith("multipart/form-data");//如果是上传文件if(multipart){try{DiskFileUploadupload=newDiskFileUpload();//使用apache进行上传//设置编码upload.setHeaderEncoding(encoding);//解析上传的数据List<FileItem>fileItems=upload.parseRequest(request);//遍历for(Iterator<FileItem>it=fileItems.iterator();it.hasNext();){//获取当前的FileItemFileItemitem=(FileItem)it.next();//如果是文本域if(item.isFormField()){params.put(item.getFieldName(),item.getString(encoding));}else{//替换特殊字符Stringfilename=item.getName().replace("\\","/");filename=filename.substring(filename.lastIndexOf("/")+1);//保存到系统临时文件夹中java.io.Filefile=newFile(System.getProperty("java.io.tmpdir"),filename);//新建文件输出流OutputStreamops=newFileOutputStream(file);//输出到文件流中ops.write(item.get());//关闭文件流ops.close();//将值放到Map中params.put(item.getFieldName(),file);}}}catch(Exceptione){e.printStackTrace();}}}@OverridepublicObjectgetAttribute(Stringname){//如果是上传文件,则从Map中取值,支持直接获取文件对象if(multipart&&params.containsKey(name)){returnparams.get(name);}returnsuper.getAttribute(name);}@OverridepublicStringgetParameter(Stringname){//如果是上传文件,则从Map中取值,if(multipart&&params.containsKey(name)){returnparams.get(name).toString();}returnsuper.getParameter(name);}}}

好了,Filter写完了,那么就修改配置文件web.xml吧,如下:

<filter><filter-name>Uploadfilter</filter-name><filter-class>yin.filter.Uploadfilter</filter-class></filter><filter-mapping><filter-name>Uploadfilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>

以上只是文件上传的Filter,那么该怎样使用了。放心,在下会说滴:

我们现在先写一个简单的上传的jsp文件,

<body><!--包含上传文件的表单--><formaction="upload"method="post"enctype="multipart/form-data">用户名:<inputtype="text"value=""name="uname"><br>密&nbsp;&nbsp;码:<inputtype="password"value=""name="psw"><br>头&nbsp;&nbsp;像:<inputtype="file"name="file"><br><inputtype="submit"value="注册"></form></body>

由于样式什么的没有调整,难看点也是无所谓的吧!

然后在servlet中使用:

protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{request.setCharacterEncoding("utf-8");response.setContentType("text/html;charset=utf-8");//读取表单内容Stringname=request.getParameter("uname");Stringpsw=request.getParameter("psw");FileheadPic=(File)request.getAttribute("file");FileWriterWrapperwrite=newFileWriterWrapper(request,headPic);}

大家有没有发现,这样选取表单中的内容是比较方便的,那么然后

FileWriterWrapperwrite=newFileWriterWrapper(request,headPic);

这一行代码就是将读取到的文件写入到硬盘中了,

packageyin.usual;importjava.io.File;importjava.io.FileInputStream;importjava.io.FileOutputStream;importjava.io.IOException;importjavax.servlet.ServletContext;importjavax.servlet.http.HttpServletRequest;publicclassFileWriterWrapper{publicFileWriterWrapper(){//TODOAuto-generatedconstructorstub}//文件写入的方法publicFileWriterWrapper(HttpServletRequestrequest,Filefile){try{//读取上下文配置,获取路径ServletContextcontext=request.getServletContext();Stringfilename=context.getInitParameter("filename");//获取文件保存路径filename=context.getRealPath(filename);//如果路径不存在,则创建if(!newFile(filename).isDirectory()){System.out.println("文件不存在,正在创建。。。");newFile(filename).mkdirs();}//获取文件名Stringpicname=file.getName().replace("/","\\");picname=picname.substring(picname.lastIndexOf("\\")+1,picname.length());//获取文件保存位置Stringpath=filename+"\\"+picname;System.out.println("文件保存在:"+path);FileInputStreamfis=newFileInputStream(file);FileOutputStreamfos=newFileOutputStream(path);byte[]bs=newbyte[1024*1024*4];intlen=0;while((len=fis.read(bs))!=-1){fos.write(bs,0,len);}//关闭文件fis.close();fos.close();System.out.println("文件写入成功");}catch(IOExceptione){System.out.println("文件写入失败");e.printStackTrace();}}}

接下来,大家看看配置:

<context-param><param-name>filename</param-name><param-value>/imgs</param-value></context-param>

看到这,不知道大家有没有一个疑问,如果表单中的上传文件有多个,那么怎么办?如果这样就需要修改

FileWriterWrapper

类了,可以将获取上下文配置中的路径放在Servlet中,这样就可以了,具体操作在下就不书写了。。

以上内容如有错误,欢迎指出。。。