struts2多文件上传(2)

struts2实现文件上传和下载
前言:好久没有发新随笔了,不是没有在学习,而是这个月BRAS用得太猛了,后面几天都没网上了!好了,言归正传,用一个小工程总结一下最近学习Struts2的心得体会。
开发环境:jdk1.6 + tomcat6.0.14 + Myeclipse6.0 + Struts2.0.14 + commons-fileupload-1.2.1 + commons-io-1.4
学习教程:风中叶 浪曦_Struts2应用开发系列
小项目需求分析或实现的功能:
(1).用户只有输入正确的邀请码之后才能进行注册,否则填写注册信息之后提交没有反应,还会停留在注册页面。
(2).用户注册之后可以上传文件,也可以下载其中的文件。
分析:struts2并没有实现文件的上传和下载,我们需要到apache网站去下载commons-fileupload-1.2.1 和 commons-io-1.4 ,并把其中的核心jar包导入到工程。我们可以使用拦截器来实现功能(1)。

具体步骤:
1.新建web项目 命名为struts2demo
struts2多文件上传(2)_第1张图片

2.向工程中导入所需要的jar包 必要的jar包有七个
struts2多文件上传(2)_第2张图片

3.在web.xml文件中注册struts2
<? xml version="1.0" encoding="UTF-8" ?>
< web-app  version ="2.4"  
    xmlns
="http://java.sun.com/xml/ns/j2ee"  
    xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"  
    xsi:schemaLocation
="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
>
  
  
< filter >
     
< filter-name > struts2 </ filter-name >
     
< filter-class > org.apache.struts2.dispatcher.FilterDispatcher </ filter-class >  
  
</ filter >
 
  
< filter-mapping >
     
< filter-name > struts2 </ filter-name >
     
< url-pattern > /* </ url-pattern >
  
</ filter-mapping >
  
</ web-app >

4.编写输入邀请码的JSP页面invite.jsp
<% @ page language="java" contentType="text/html; charset=GBK"
    pageEncoding
="GBK"
%>
<% @ taglib prefix="s" uri="/struts-tags"  %>    

<! DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" >
< html >
< head >< title > 验证码校验 </ title ></ head >
< body >    
    
< table  align ="center"  width ="60%" >< tr >< td  style ="color:red" >< s:fielderror /></ td ></ tr ></ table >    
    
< form  action ="invite.action"  method ="post" >
        请输入您的验证码:
< br >
       
< input  type ="text"  name ="invitedcode" >< br >
       
< input  type ="submit"  value ="提交验证码" >
       
< input  type ="reset"  value ="重新输入" >    
    
</ form >    
</ body >
</ html >

5. 在Tomcat的server.xml中加入工程

6.启动Tomcat服务器 测试当前所做是否有错误
struts2多文件上传(2)_第3张图片

以上表明当前设置没有错误!
7.在src下新建com.demo.action包,并在其中新建InviteAction类,此类要继承ActionSupport类
struts2多文件上传(2)_第4张图片

package  com.demo.action;

import  java.util.Map;
import  com.opensymphony.xwork2.ActionContext;
import  com.opensymphony.xwork2.ActionSupport;

public   class  InviteAction  extends  ActionSupport  {
    
private String invitedcode;

    
public String getInvitedcode() {
        
return invitedcode;
    }


    
public void setInvitedcode(String invitedcode) {
        
this.invitedcode = invitedcode;
    }


    @Override
    
public String execute() throws Exception {
        
if("220081078".equals(this.getInvitedcode())){       
            
return SUCCESS;
        }

        
else{
            
this.addFieldError("invitedcode""输入的邀请码不正确!请再次输入!");
            
return INPUT;
        }

    }

}


类中规定只有输入的验证码为220081078,才能进入到注册页面,否则会出现错误的提示信息并回到原页面继续输入。

8. 在src下新建struts.xml文件,在struts.xml文件中对InviteAction进行注册
<? xml version="1.0" encoding="UTF-8"  ?>
<! DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd"
>

< struts >

    
< package  name ="struts2demo"  extends ="struts-default" >

        
< action  name ="invite"  class ="com.demo.action.InviteAction" >            
            
< result  name ="input" > /invite.jsp </ result >
            
< result  name ="success" > /register.jsp </ result >
        
</ action >     
         
    
</ package >
    
</ struts >

9.新建 register.jsp页面,并加入如下代码
<% @ page language="java" import="java.util.*" pageEncoding="GBK" %>
<% @ taglib prefix="s" uri="/struts-tags"  %>

<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" >
< html >
  
< head >
   
< title > 注册页面 </ title >

    
< script  type ="text/javascript" >
        
function validate(){
           
var usernameValue = document.getElementById("usernameId").value;
           
var passwordValue = document.getElementById("passwordId").value;
           
var repasswordValue = document.getElementById("repasswordId").value;
           
           
if(usernameValue.length == 0){
               alert(
"用户名不能为空!");
               
return false;
           }

           
else if(usernameValue.length < 6 || usernameValue.length > 16){
               alert(
"用户名只能由6-16位字母和数字组成!");
               
return false;
           }

           
           
if(passwordValue.length == 0){
               alert(
"密码不能为空!");
               
return false;
           }

           
else if(passwordValue.length < 6 || passwordValue.length > 16){
               alert(
"用户名只能由6-16位字母和数字组成!");
               
return false;
           }

           
           
if(passwordValue != repasswordValue){
               alert(
"两次输入的密码不一致!");
               
return false;
           }

           
           
return true;
        }

    
</ script >

  
</ head >
  
  
< body >

      
< table  align ="center"  width ="60%" >< tr >< td  style ="color:green" >< s:fielderror /></ td ></ tr ></ table >

      
< s:form  action ="register"  theme ="simple"  method ="post" >
      
      
< table  align ="center"  width ="40%"  border ="2" >
         
< tr >< td > *用户名: </ td >< td >   < s:textfield  name ="username"  id ="usernameId" ></ s:textfield >   </ td ></ tr >
         
< tr >< td > *密码: </ td >< td >   < s:password  name ="password"  id ="passwordId" ></ s:password >   </ td ></ tr >
         
< tr >< td > *重复密码: </ td >< td >   < s:password  name ="repassword"  id ="repasswordId" ></ s:password >   </ td ></ tr >
         
< tr >< td > 年龄: </ td >< td >   < s:textfield  name ="age" ></ s:textfield >   </ td ></ tr >
         
< tr >< td > 生日: </ td >< td >   < s:textfield  name ="birthday" ></ s:textfield >   </ td ></ tr >
         
< tr >< td >   < s:submit  value ="注册"  onclick ="validate()" ></ s:submit ></ td >< td >< s:reset  value ="重填" ></ s:reset >   </ td ></ tr >
               
      
</ table >
      
</ s:form >
   
  
</ body >
</ html >
其中脚本validate()方法对输入进行客户端的验证,如果没有输入必填项(用户名和密码)或输入的长度超过限制,都会提示相应的错误信息。

10.对以上所做工作进行测试
如果输入错误的邀请码 如2200810888 则显示结果如下
struts2多文件上传(2)_第5张图片

如果输入正确的邀请码 如220081078 则转入到注册页面 测试成功!
struts2多文件上传(2)_第6张图片

11.在action包中创建RegisterAction类 并编写如下代码
package  com.demo.action;

import  java.util.Calendar;
import  java.util.Date;

import  com.opensymphony.xwork2.ActionSupport;

public   class  RegisterAction  extends  ActionSupport  {
    
private String username;
    
private String password;
    
private String repassword;
    
private int age;
    
private Date birthday;

    
public String getUsername() {
        
return username;
    }


    
public void setUsername(String username) {
        
this.username = username;
    }


    
public String getPassword() {
        
return password;
    }


    
public void setPassword(String password) {
        
this.password = password;
    }


    
public String getRepassword() {
        
return repassword;
    }


    
public void setRepassword(String repassword) {
        
this.repassword = repassword;
    }


    
public int getAge() {
        
return age;
    }


    
public void setAge(int age) {
        
this.age = age;
    }


    
public Date getBirthday() {
        
return birthday;
    }


    
public void setBirthday(Date birthday) {
        
this.birthday = birthday;
    }


    @Override
    
public String execute() throws Exception {
        
        
return SUCCESS;
    }


    @Override
    
public void validate() {
        
if(null == username || username.length()<6 || username.length()>16){
            
this.addActionError("用户名应该由6-10位字母和数字组成");
          }

        
if(null == password || password.length()<6 || password.length()>16){
                
this.addActionError("密码应该由6-10位字母和数字组成");
          }

        
else if(!(repassword.equals(password))){
                
this.addActionError("两次输入密码不一致!");
          }

        
if(age<0 || age>150){
                
this.addActionError("年龄应该在0-150之间!");
          }

        
    }
    
}

 其中validate()方法对输入进行服务器端的验证,以提高安全性。

12.在struts.xml文件中对RegisterAction进行注册 在package下加入如下代码

< action  name ="register"  class ="com.demo.action.RegisterAction" >            
            
< result  name ="input" > /register.jsp </ result >
            
< result  name ="success" > /registersuccess.jsp </ result >
        
</ action >

13. 编写registersuccess.jsp页面
<% @ page language="java" contentType="text/html; charset=GBK"
    pageEncoding
="GBK"
%>
<! DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" >
< html >
< head >

< title > 注册成功 </ title >
</ head >
< body >
    恭喜您已经注册成功!
< br >
    一下是您的注册信息:
< br >
    用户名:${requestScope.username}
< br >
    密码:${requestScope.password}
< br >
    年龄:${requestScope.age}
< br >
    生日:${requestScope.birthday}
< br >

    
< href ="upload.jsp" > 开始上传文件 </ a >
</ body >
</ html >

14.对上述工作进行测试
如果进行不合法的注册 如没有填入必填项或者输入长度不合法 会出现相关错误提示信息
struts2多文件上传(2)_第7张图片

如果输入合法注册信息,将转到注册成功页面。
struts2多文件上传(2)_第8张图片
struts2多文件上传(2)_第9张图片
15. 编写文件上传页面upload.jsp代码
<% @ page language="java" contentType="text/html; charset=GBK"
    pageEncoding
="GBK"
%>
<% @ taglib prefix="s" uri="/struts-tags" %>

<! DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" >
< html >
< head >
< meta  http-equiv ="Content-Type"  content ="text/html; charset=ISO-8859-1" >
< title > 上传文件页面 </ title >

   
< script  type ="text/javascript" >
      
function addMore(){
         
var td = document.getElementById("more");
         
var br = document.createElement("br");
         
var input = document.createElement("input");
         
var button = document.createElement("input");
         input.type 
= "file";
         input.name 
= "file";
         button.type
="button";
         button.value
="Remove";
         
         button.onclick 
= function(){
            td.removeChild(br);
            td.removeChild(input);
            td.removeChild(button);
         }

         
         
         td.appendChild(br);
         td.appendChild(input);
         td.appendChild(button);
      
      }

   
   
</ script >


</ head >
< body >
    
     
< table  align ="center"  width ="60%" >< tr >< td  style ="color:green" >< s:fielderror /></ td ></ tr ></ table >
    
     
< s:form  action ="upload"  theme ="simple"  enctype ="multipart/form-data"  method ="post" >
      
      
< table  align ="center"  width ="50%"  border ="2" >
      
         
< tr >< td > 用户名: </ td >< td >   < s:textfield  name ="username" ></ s:textfield >   </ td ></ tr >
         
< tr >< td > 密码: </ td >< td >   < s:password  name ="password" ></ s:password >   </ td ></ tr >
         
< tr >< td > 选择文件: </ td >    < td  id ="more" >< s:file  name ="file" ></ s:file >< input  type ="button"  value ="上传更多"  onclick ="addMore()" ></ td >   </ tr >
         
< tr >< td >< s:submit  value =" 全部上传 " ></ s:submit ></ td ></ tr >
               
      
</ table >
      
</ s:form >
    
</ body >
</ html >
  该页面允许用户上传足够多的文件。点击“上传更多...”按钮一次会添加一个上传文件textfield,点击‘Remove’按钮可以消去该行。

16. 编写UploadAction类代码 将文件上传到upload文件夹
package  com.demo.action;

import  java.io.File;
import  java.io.FileInputStream;
import  java.io.FileOutputStream;
import  java.io.InputStream;
import  java.io.OutputStream;
import  java.util.List;

import  org.apache.struts2.ServletActionContext;

import  com.opensymphony.xwork2.ActionSupport;

public   class  UploadAction  extends  ActionSupport  {
    
private String username;
    
private String password;
    
private List<File> file;
    
private List<String> fileFileName;
    
private List<String> fileContentType;
    
public String getUsername() {
        
return username;
    }

    
public void setUsername(String username) {
        
this.username = username;
    }

    
public String getPassword() {
        
return password;
    }

    
public void setPassword(String password) {
        
this.password = password;
    }

    
    
public List<File> getFile() {
        
return file;
    }

    
public void setFile(List<File> file) {
        
this.file = file;
    }

    
public List<String> getFileFileName() {
        
return fileFileName;
    }

    
public void setFileFileName(List<String> fileFileName) {
        
this.fileFileName = fileFileName;
    }

    
public List<String> getFileContentType() {
        
return fileContentType;
    }

    
public void setFileContentType(List<String> fileContentType) {
        
this.fileContentType = fileContentType;
    }

    
    @Override
    
public String execute() throws Exception {
        
        
        
for(int i = 0;i<file.size();i++){
            InputStream is 
= new FileInputStream(file.get(i));
            
            String root 
= ServletActionContext.getRequest().getRealPath("/upload");
            
            File destFile 
= new File(root,this.getFileFileName().get(i));
            
            OutputStream os 
= new FileOutputStream(destFile);
            
            
byte[] buffer = new byte[400];
            
int length = 0 ;
            
while((length = is.read(buffer)) > 0){
                os.write(buffer, 
0, length);
            }

            
            is.close();
            os.close();
        }

        
        
return SUCCESS;
    }

    
}


17. 在struts.xml文件中对UploadAction进行注册
      < action  name ="upload"  class ="com.demo.action.UploadAction" >
            
< result  name ="success" > /uploadsuccess.jsp </ result >
            
< result  name ="input" > /upload.jsp </ result >
            
< interceptor-ref  name ="fileUpload" >
                
< param  name ="maximumSize" > 4096000 </ param >
                
< param  name ="allowedTypes" > application/vnd.ms-powerpoint </ param >
            
</ interceptor-ref >  
            
< interceptor-ref  name ="defaultStack" ></ interceptor-ref >
        
</ action >
 上传文件时会用到内部的fileUpload拦截器 其中对上传文件的大小和类型进行了限制 如上也许上传最大文件为4000K,文件类型只能为ppt类型。

18.对上传文件是的错误信息进行改进,系统提供的错误信息(如文件大小或类型不合法)可读性很差。
    在struts.xml中加入如下语句 
< constant  name ="struts.custom.i18n.resources"  value ="message" ></ constant >
    
    
< constant  name ="struts.i18n.encoding"  value ="gbk" ></ constant >
   第一句是配置错误信息message.properties,第二句是对上传文件过程中的中文乱码进行更正。
   在src目录下新建文件message.properties ,文件内容为
struts.messages.error.content.type.not.allowed=\u4e0a\u4f20\u7684\u6587\u4ef6\u7c7b\u578b\u4e0d\u5141\u8bb8 \u8bf7\u91cd\u8bd5
struts.messages.error.file.too.large=\u4e0a\u4f20\u6587\u4ef6\u7684\u5927\u5c0f\u8d85\u8fc7\u9650\u5236
  右边的编码可以通过Java提供的native2ascii进行转换。

19. 编写download.jsp页面
<% @ page language="java" contentType="text/html; charset=GBK"
    pageEncoding
="GBK"
%>
    
<% @ taglib prefix="s" uri="/struts-tags"  %>
<! DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" >
< html >
< head >

< title > 文件下载 </ title >
</ head >
< body >
    欢迎来到下载页面!
< br >
   
< s:a  href ="/struts2/download.action" > 点击下载 </ s:a >

</ body >
</ html >

  20. 编写DownloadAction类代码 假设我们要下载的是upload文件夹下的Struts2.ppt文件

 

package  com.demo.action;

import  java.io.InputStream;

import  org.apache.struts2.ServletActionContext;

import  com.opensymphony.xwork2.ActionSupport;

public   class  DownloadAction  extends  ActionSupport  {
     
    
public InputStream getDownloadFile(){
        
return ServletActionContext.getServletContext().getResourceAsStream("/upload/Struts2.ppt");
        
    }


    @Override
    
public String execute() throws Exception {
        
return SUCCESS;
    }

    
    
}




 

21.在struts.xml文件中对DownloadAction进行注册 要注意其中的参数名称

  < action  name ="download"  class ="com.demo.action.DownloadAction" >  
            
< result  name ="success"  type ="stream" >
               
< param  name ="contentType" > application/vnd.ms-powerpoint </ param >
               
< param  name ="contentDisposition" > filename="Struts2.ppt" </ param >
               
< param  name ="inputName" > downloadFile </ param >
            
</ result >
        
</ action >


 22.对以上步骤进行测试

上传文件类型不合法
struts2多文件上传(2)_第10张图片


上传合法内容,如我们上传三个ppt文件 则能成功
struts2多文件上传(2)_第11张图片

struts2多文件上传(2)_第12张图片


点击到下载页面下载文件
struts2多文件上传(2)_第13张图片
23.实现邀请码功能 以上并没有实现邀请码的功能,即用户可以直接进入到注册页面进行注册。我们需要编写一个拦截器实现该功能。
(1) 编写InviteInterceptor拦截器代码
   
package  com.demo.interceptor;

import  java.util.Map;

import  com.opensymphony.xwork2.Action;
import  com.opensymphony.xwork2.ActionInvocation;
import  com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public   class  InviteInterceptor  extends  AbstractInterceptor  {

    @Override
    
public String intercept(ActionInvocation invocation) throws Exception {
        Map map 
= invocation.getInvocationContext().getSession();
        
if(map.get("invitedcode"== null){
            
return Action.INPUT;
        }
else{
            
return invocation.invoke();
        }

    }


}


(2) 改写InviteAction的execute()方法 加入如下语句
     struts2多文件上传(2)_第14张图片
(3) 在struts.xml中注册拦截器 并在register的action中加入拦截器
   最终struts.xml的代码
<? xml version="1.0" encoding="UTF-8"  ?>
<! DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd"
>

< struts >
    
< constant  name ="struts.custom.i18n.resources"  value ="message" ></ constant >
    
    
< constant  name ="struts.i18n.encoding"  value ="gbk" ></ constant >
    
< constant  name ="struts.multipart.saveDir"  value ="/upload" ></ constant >
  
    
< package  name ="struts2demo"  extends ="struts-default" >
    
        
< interceptors >             
           
< interceptor  name ="invite"  class ="com.demo.interceptor.InviteInterceptor" ></ interceptor >
        
</ interceptors >     
        
       

        
< action  name ="invite"  class ="com.demo.action.InviteAction" >            
            
< result  name ="input" > /invite.jsp </ result >
            
< result  name ="success" > /register.jsp </ result >
        
</ action >     
        
        
< action  name ="register"  class ="com.demo.action.RegisterAction" >            
            
< result  name ="input" > /register.jsp </ result >
            
< result  name ="success" > /registersuccess.jsp </ result >
            
            
< interceptor-ref  name ="invite" ></ interceptor-ref >
            
< interceptor-ref  name ="defaultStack" ></ interceptor-ref >
        
</ action >
        
        
< action  name ="upload"  class ="com.demo.action.UploadAction" >
            
< result  name ="success" > /uploadsuccess.jsp </ result >
            
< result  name ="input" > /upload.jsp </ result >
            
< interceptor-ref  name ="fileUpload" >
                
< param  name ="maximumSize" > 4096000 </ param >
                
< param  name ="allowedTypes" > application/vnd.ms-powerpoint </ param >
            
</ interceptor-ref >  
            
< interceptor-ref  name ="defaultStack" ></ interceptor-ref >
        
</ action >
        
         
< action  name ="download"  class ="com.demo.action.DownloadAction" >  
            
< result  name ="success"  type ="stream" >
               
< param  name ="contentType" > application/vnd.ms-powerpoint </ param >
               
< param  name ="contentDisposition" > filename="Struts2.ppt" </ param >
               
< param  name ="inputName" > downloadFile </ param >
            
</ result >
        
</ action >
         
    
</ package >
    
</ struts >

24.最后的测试
如果没有进行邀请码的验证 直接进入到注册页面进行注册 将不成功。达到项目需求。

总结:这是最近三天学习的结果,很喜欢风中叶老师的讲解。他没有给我们代码,却每一步都讲得很仔细,还带着我们一步步地看相关的帮助文档,会继续支持风中叶老师的!开发还是要自己多看看各种文档,这样才能学习到正宗的知识!

由于随笔附件大小有限制 上传的代码中删除了struts2的5个jar包 可自行加入
本随笔代码 代码

你可能感兴趣的:(struts,MyEclipse,测试,buffer,input,encoding)