三. 实现多文件上传
在实现多文件上传时,有了单文件上传的基础上,是非常简单的,只需要将原来的对象,改变成数组即可。
将File upload改成File[] upload即可。 uploadFileName和uploadeContentType也同样需要改变成字符串数组的样式。
三.一 编写 /content/login2.jsp 页面
login.jsp页面
file是多选形式,用多个name值相同的样式。
<s:form action="MoreFile_multiple.action" namespace="/" method="post" enctype="multipart/form-data"> 用户名: <s:textfield name="name"/> <br/> 密码: <s:password name="password"/><br/> <!-- 名称相同 --> 上传文件1:<s:file name="upload"/><br/> 上传文件2:<s:file name="upload"/><br/> <s:submit value="提交"/> <s:reset value="重置"/> </s:form>
三.二 创建 MoreFileAction.java
MoreFileAction:
package com.yjl.web.action; import java.io.File; import java.io.IOException; import org.apache.commons.io.FileUtils; import org.apache.log4j.Logger; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionSupport; /** * @author 两个蝴蝶飞 * @version 创建时间:Aug 28, 2018 8:35:56 AM * 关于文件上传和下载的Action实现 */ public class FileAction extends ActionSupport{ private static final long serialVersionUID = 1L; private Logger logger=Logger.getLogger(FileAction.class); /** * 关于文件上传的具体的操作 * @param uploade 与前端表单中file标签的name值相同. * @param XxxFileName 上传文件的名称 * @param XxxContentType 上传文件的类型 */ private File []upload; private String []uploadFileName; private String []uploadContentType; //实现它们三个的setter和getter方法 public File[] getUpload() { return upload; } public void setUpload(File []upload) { this.upload = upload; } public String[] getUploadFileName() { return uploadFileName; } public void setUploadFileName(String []uploadFileName) { this.uploadFileName = uploadFileName; } public String[] getUploadContentType() { return uploadContentType; } public void setUploadContentType(String []uploadContentType) { this.uploadContentType = uploadContentType; } /** *多文件上传操作 */ public String multiple(){ //在实际开发中,需要判断一下是否上传了文件,即upload是否为空,不为空,才进行上传的操作。 if(upload!=null){ for(int i=0;i<upload.length;i++){ //1.输出上传的类型 logger.info("上传文件的名称用File取得:"+this.getUpload()[i].getName()); logger.info("直接用属性取得名称:"+this.getUploadFileName()[i]); logger.info("文件上传的类型:"+this.getUploadContentType()[i]); //2.设置上传文件的放置位置,通常放在服务器下面的upload文件夹下. String path=ServletActionContext.getServletContext().getRealPath("/upload"); //3.这是一个目录,如果这个目录不存在,需要创建这个目录(包括其父目录) File srcFile=new File(path); if(!srcFile.exists()){ srcFile.mkdirs(); } //4.通常还需要对上传的文件名进行UUID的操作,使文件名不能重复。这里不做处理 String fileName=this.getUploadFileName()[i]; //5.调用FileUtils类执行上传的操作. try { FileUtils.copyFile(upload[i],new File(srcFile,fileName)); logger.info("文件上传成功"); } catch (IOException e) { e.printStackTrace(); } } } return SUCCESS; } }
三.三 配置struts.xml 文件
struts.xml
<action name="MoreFile_*" class="com.yjl.web.action.MoreFileAction" method="{1}"> <result name="success">/WEB-INF/content/success.jsp</result> </action>
三.四 重启服务器测试
输入网址: http://localhost:8080/Struts_File/login2
进行相关的测试:
上传文件:
控制台打印输出:
查看Tomcat 目录:
多文件上传操作成功。
四. 文件上传实例应用
在实际项目中,不仅要能正常的上传文件,还应该把上传文件的位置返回。
前端页面和struts.xml的配置都一样,主要是对Action的处理。 我通常的作法是创建一个BaseAction的类,
与第四章项目中的BaseAction相同,只是这里添加了上传的操作。
BaseAction
package com.yjl.web.action; import java.io.File; import java.io.IOException; import java.lang.reflect.ParameterizedType; import java.text.SimpleDateFormat; import org.apache.commons.io.FileUtils; import org.apache.log4j.Logger; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.ModelDriven; /** * @author 两个蝴蝶飞 * @version 创建时间:2018年8月23日 下午4:40:13 * @description BaseAction的工具类 */ @SuppressWarnings(value= {"rawtypes","unchecked"}) public class BaseAction<T> extends ActionSupport implements ModelDriven<T>{ private static final long serialVersionUID = -7180401147510521582L; private Logger logger=Logger.getLogger(BaseAction.class); private T t; private Class clazz; public BaseAction() { //得到当前的类 Class class1=this.getClass(); //得到运行中的父类 ParameterizedType parameterizedType=(ParameterizedType) class1.getGenericSuperclass(); clazz=(Class) parameterizedType.getActualTypeArguments()[0]; try { t=(T) clazz.newInstance(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } logger.info("当前类的类:"+clazz.getName()+"完成初始化"); } @Override public T getModel() { return t; } //添加实现文件上传和下载的操作 /** * 关于文件上传的具体的操作 * @param uploade 与前端表单中file标签的name值相同. * @param XxxFileName 上传文件的名称 * @param XxxContentType 上传文件的类型 */ private File upload; private String uploadFileName; private String uploadContentType; //实现它们三个的setter和getter方法 public File getUpload() { return upload; } public void setUpload(File upload) { this.upload = upload; } public String getUploadFileName() { return uploadFileName; } public void setUploadFileName(String uploadFileName) { this.uploadFileName = uploadFileName; } public String getUploadContentType() { return uploadContentType; } public void setUploadContentType(String uploadContentType) { this.uploadContentType = uploadContentType; } /** *得到上传的路径 */ public String getUploadPath(){ //在实际开发中,需要判断一下是否上传了文件,即upload是否为空,不为空,才进行上传的操作。 String contextPath=null; if(upload!=null){ //1.输出上传的类型 logger.info("上传文件的名称用File取得:"+this.getUpload().getName()); logger.info("直接用属性取得名称:"+this.getUploadFileName()); logger.info("文件上传的类型:"+this.getUploadContentType()); //2.设置上传文件的放置位置,通常放在服务器下面的upload文件夹下. String path=ServletActionContext.getServletContext().getRealPath("/upload"); //3.这是一个目录,如果这个目录不存在,需要创建这个目录(包括其父目录) File srcFile=new File(path); if(!srcFile.exists()){ srcFile.mkdirs(); } //4.通常还需要对上传的文件名进行UUID的操作,使文件名不能重复。文件的返回路径是fileName. String fileName=path+getAnglePath(this.getUploadFileName()); //5.调用FileUtils类执行上传的操作. try { //写复制方法 FileUtils.copyFile(upload,new File(fileName)); //将fileName进行相应的处理,去掉前面的一些无用的东西。 得到项目名 String context=ServletActionContext.getRequest().getContextPath().substring(1); contextPath=getPath(fileName,context); logger.info("在Tomcat下的目录为:"+contextPath); logger.info("文件上传成功"); } catch (IOException e) { e.printStackTrace(); } } return contextPath; } /** * 将一个文件名设置成唯一的文件名 * @param fileName 普通的文件名 * @return 返回一个唯一的文件名 */ public String getAnglePath(String fileName) { //不采用UUID的形式,可以自定义当前的时间字符串来处理. SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMddHHmmssSSS"); String angle=sdf.format(new java.util.Date()); return File.separator+angle+"_"+fileName; } /** * 将磁盘上的文件在Tomcat下的文件,转换成在Tomcat上的文件 * @param realPath 在磁盘上的路径 * @param name 项目名 * @return 将磁盘上的文件在Tomcat下的文件,转换成在Tomcat上的文件 */ public String getPath(String realPath, String name) { int index = realPath.indexOf(name); String[] args = realPath.substring(index).split("\\\\"); StringBuffer sb = new StringBuffer("/"); for (int i = 0; i < args.length; i++) { if (i != args.length - 1) { sb.append(args[i]).append("/"); } else { sb.append(args[i]); } } return sb.toString(); } }
在我们写的FileAction中,只需要继承BaseAction类,然后调用方法即可。
package com.yjl.web.action; import org.apache.log4j.Logger; import com.yjl.pojo.User; /** * @author 两个蝴蝶飞 * @version 创建时间:Aug 28, 2018 8:35:56 AM * 关于文件上传和下载的Action实现 */ public class FileAction extends BaseAction<User>{ private static final long serialVersionUID = 1L; private Logger logger=Logger.getLogger(FileAction.class); public String login(){ String path=getUploadPath(); logger.info("上传的路径是:"+path); return SUCCESS; } }
文件上传后的控制台:
如果没有上传文件的话,
这样就完成了。
如果在上传时,出现中文乱码的问题,那是因为没有在 struts.xml中添加格式处理常量:
<!--修改国际化编码 --> <constant name="struts.i18n.encoding" value="UTF-8"></constant>
文件上传操作完成。