Struts1 与 Struts2多文件下传的比较
Struts1 与 Struts2多文件上传的比较
STRUTS 1 部分
STRUTS 1 的文件上传定义了专门的文件处理接口FormFile。查看源码才知道,FormFile与File完全不是一回事,所以想将FormFile转为File再处理就行不通了。
第一次写上传时,我使用了common-upload组件进行文件上传,后来发现STRUTS在request中根本读不到文件。后来查了一些资料才发现Struts在Action处理逻辑之前已经对request中的表单数据进行了wrap。所以就只能老老实实的按STRUTS自己的文件上传方法写了。
多文件上传与单个文件上传有些不太一样,单文件上传只需要在Form类中给一个FormFile类型的属性,就能接受到页面提交的文件数据。多文件上传时,STRUTS在页面端将多个文件wrap成了一个数组,转给From类时又wrap成了List。所以我们在页面上使用数组形式对文件进行提交,在Form类中用List对文件进行接收。以下是相关的代码:
1.jsp页面代码
2.Form代码
3.Action处理代码
注意,因为我在页面中使用的数组为uploadFile[],所以在Form类中添加了getUploadFile(int index)。因为<html:file/>标签上传的文件在STRUTS中都是由FormFile类接收处理的,所以,在页面中我们使用uploadFile[i].file,它表示的是UploadFile类的file属性,即一个FormFile类对象。
如果,在上传文件中,我们需要对文件进行改名,那么FormFile.setFileName()是用不了的。这个具体为什么我也没有研究,不过我们可以直接将OutputStream输出文件的名字重新换一个就可以了。
STRUTS 2 部分
struts2经过struts1的改进,或者说webwork本身在这方面的功能就比较强大(webwork具体我没怎么研究过),在使用方法上进步了很多,只须以下三步便可以实现多文件的上传。
1.实现action类,使用数组进行存储。需要提供contentType及fileName属性存储相关属性值。
2.配置action,设置拦截器
3.配置jsp页面,使用表单上传
注:servlet 2.4之前的版本还得在web.xml中配置clean-up。
STRUTS 1 部分
STRUTS 1 的文件上传定义了专门的文件处理接口FormFile。查看源码才知道,FormFile与File完全不是一回事,所以想将FormFile转为File再处理就行不通了。
第一次写上传时,我使用了common-upload组件进行文件上传,后来发现STRUTS在request中根本读不到文件。后来查了一些资料才发现Struts在Action处理逻辑之前已经对request中的表单数据进行了wrap。所以就只能老老实实的按STRUTS自己的文件上传方法写了。
多文件上传与单个文件上传有些不太一样,单文件上传只需要在Form类中给一个FormFile类型的属性,就能接受到页面提交的文件数据。多文件上传时,STRUTS在页面端将多个文件wrap成了一个数组,转给From类时又wrap成了List。所以我们在页面上使用数组形式对文件进行提交,在Form类中用List对文件进行接收。以下是相关的代码:
1.jsp页面代码
<html:file property = "uploadFile[0].file"/> <html:file property = "uploadFile[1].file"/>
2.Form代码
public class AccuseForm extends ActionForm { private List evidences; public AccuseForm(){ evidences = new ArrayList(); evidences.add(new UploadFile()); } public UploadFile getUploadFile(int index){ int size = evidences.size(); if(index > size - 1){ for(int i = 0; i < index - size + 1; i++){ evidences.add(new UploadFile()); } } return (UploadFile)evidences.get(index); } public List getEvidences() { return evidences; } public void setEvidences(List evidence) { this.evidences = evidence; } } public class UploadFile implements Serializable { private FormFile file; private String newName; public FormFile getFile(){ //System.out.println("run in uploadFile.getFile()"); return this.file; } public void setFile(FormFile file){ this.file = file; } }
3.Action处理代码
public class AccuseAction extends DispatchAction { public ActionForward save(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response){ AccuseForm f = (AccuseForm)form; List evidences = f.getEvidences(); try{ String dir = Constants._UPLOAD_DIR; File fDir = new File(dir); if(!fDir.exists()) fDir.mkdirs(); for(int i = 0; i < evidences.size(); i++){ UploadFile uploadFile = (UploadFile)evidences.get(i); uploadFile = renameFile(uploadFile); if(uploadFile.getFile() == null){ System.out.println("file is null"); break; }else{ //System.out.println("filename:::" + file.getFileName()); //System.out.println("file size:::" + file.getFileSize()); //System.out.println(dir); uploadFile(uploadFile, dir); } } }catch(Exception e){ e.printStackTrace(); } private void uploadFile(UploadFile file, String dir) throws FileNotFoundException, IOException{ InputStream in = file.getFile().getInputStream(); OutputStream out = new BufferedOutputStream( new FileOutputStream( dir + file.getNewName() )); final int _BUFFERSIZE = 8192; int bytesRead = 0; byte[] buffer = new byte[_BUFFERSIZE]; while((bytesRead = in.read(buffer, 0, _BUFFERSIZE)) != -1){ out.write(buffer, 0, bytesRead); } out.flush(); out.close(); in.close(); } }
注意,因为我在页面中使用的数组为uploadFile[],所以在Form类中添加了getUploadFile(int index)。因为<html:file/>标签上传的文件在STRUTS中都是由FormFile类接收处理的,所以,在页面中我们使用uploadFile[i].file,它表示的是UploadFile类的file属性,即一个FormFile类对象。
如果,在上传文件中,我们需要对文件进行改名,那么FormFile.setFileName()是用不了的。这个具体为什么我也没有研究,不过我们可以直接将OutputStream输出文件的名字重新换一个就可以了。
STRUTS 2 部分
struts2经过struts1的改进,或者说webwork本身在这方面的功能就比较强大(webwork具体我没怎么研究过),在使用方法上进步了很多,只须以下三步便可以实现多文件的上传。
1.实现action类,使用数组进行存储。需要提供contentType及fileName属性存储相关属性值。
package org.xwood.struts.action; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import org.apache.struts2.ServletActionContext; public class DemoAction{ private String title; private File[] upload; private String[] uploadContentType; private String[] uploadFileName; /* //接受依赖注入的属性 private String savePath; //接受依赖注入的方法 public void setSavePath(String value) { this.savePath = value; } */ private String getSavePath() throws Exception { return ServletActionContext.getServletContext().getRealPath("upload"); } public void setTitle(String title) { this.title = title; } public void setUpload(File[] upload) { this.upload = upload; } public void setUploadContentType(String[] uploadContentType) { this.uploadContentType = uploadContentType; } public void setUploadFileName(String[] uploadFileName) { this.uploadFileName = uploadFileName; } public String getTitle() { return (this.title); } public File[] getUpload() { return (this.upload); } public String[] getUploadContentType() { return (this.uploadContentType); } public String[] getUploadFileName() { return (this.uploadFileName); } public String upload() throws Exception { File[] files = getUpload(); String path = getSavePath(); for (int i = 0 ; i < files.length ; i++) { //以服务器的文件保存地址和原文件名建立上传文件输出流 FileOutputStream fos = new FileOutputStream(path + File.separator + getUploadFileName()[i]); FileInputStream fis = new FileInputStream(files[i]); byte[] buffer = new byte[1024]; int len = 0; while ((len = fis.read(buffer)) > 0) { fos.write(buffer , 0 , len); } fos.close();// 注意:流应当关闭。 fis.close(); } return "success"; } }
2.配置action,设置拦截器
<action name = "demo_*" class = "org.xwood.struts.action.DemoAction" method = "{1}"> <result name="success" type="dispatcher">/success.jsp</result> <result name="input">index.jsp</result> <interceptor-ref name="fileUpload"> <param name="maximumSize">20000</param> <param name ="allowedTypes"> * </param> </interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </action>
3.配置jsp页面,使用表单上传
注:servlet 2.4之前的版本还得在web.xml中配置clean-up。
<filter> <filter-name>struts-cleanup</filter-name> <filter-class> org.apache.struts2.dispatcher.ActionContextCleanUp </filter-class> </filter> <filter-mapping> <filter-name>struts-cleanup</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>