Sruts2下实现多文件上传功能(后台上传app软件,做版本更新)

一:框架信息
只使用了Struts 2框架
二:需要使用的jar包
commons-fileupload.jar
commons-io.jar
如果使用struts2框架自带这2个包,不是使用Struts框架可能需要下载,版本自选,最好选新择版本。
推荐下载网址:
http://download.csdn.net/detail/mxw465508356/7221415#comment

三:JSP页面
首先上传文件、图片、文档、软件之类的在form提交或者ajax提交都需要写enctype=”multipart/form-data”,并且必须是post提交。
enctype类型有
application/x-www-form-urlencoded 在发送前编码所有字符(默认)
multipart/form-data 不对字符编码。在使用包含文件上传控件的表单时,必须使用该值。
text/plain 空格转换为 “+” 加号,但不对特殊字符编码。

JSP代码:

<form class="am-form" enctype="multipart/form-data" method="post" action="MultiPartServlet/addApp.action">
                <table class="am-table am-table-compact am-table-bordered am-text-sm">
                    <thead>
                        <tr>
                            <th class="am-text-center">
                                软件
                            th>
                            <th class="am-text-center">添加信息th>
                        tr>
                    thead>
                    <tbody>
                        <tr>
                            <th class="am-text-center">上传软件th>
                            <th class="am-text-center">
                                <input  class="am-input-sm"  type="file"  name="upload_app" style="width:550">
                            th>
                        tr>
                        <tr>
                            <th class="am-text-center">上传软件th>
                            <th class="am-text-center">
                                <input  class="am-input-sm"  type="file"  name="upload_app" style="width:550">
                            th>
                        tr>
                        <tr>
                            <th class="am-text-center">上传软件th>
                            <th class="am-text-center">
                                <input  class="am-input-sm"  type="file"  name="upload_app" style="width:550">
                            th>
                        tr>

                         <tr>
                            <th class="am-text-center">app软件类型th>
                            <th class="am-text-center">
                                <select name="coupon_type" class="am-input-sm">
                                    <option value="1">安卓软件option>
                                    <option value="2">苹果软件option>
                                select>
                            th>
                        tr>
                        <tr>
                            <th class="am-text-center">app类别th>
                            <th class="am-text-center">
                                <select name="order_type" class="am-input-sm">
                                    <option value="1">客户端option>
                                    <option value="2">司机端option>
                                select>
                            th>
                        tr>
<tr>
                            <th class="am-text-center">软件版本号th>
                            <th class="am-text-center">
                                <input type="text" name="version_number">
                            th>
                        tr>
                    tbody>
                table>
                <div align="center">
                    <input class="am-btn am-btn am-btn-primary" type="submit" value="上传" id="subbut" />${errMsg}
                div>
            form>

三:后台代码
首先JSP页面上传的是一个文件,已经变成了一种流的形式传入后台,所以其中附带了许多的Input文本框,用普通的方式request.getParameter(“”)是得不到数据的,需要进行特殊处理,需要确定Struts的版本是什么,如果不确定就用以下面的方法进行试试吧。

1.首先创建一个类RequestParseWrapper,最好名字就以这个命名,假设这个类是在com.s下面,这个类的方法没有做什么处理,但需要写一个这个类。
package com.s;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest;

public class  RequestParseWrapper extends JakartaMultiPartRequest{
    @Override
    public void parse(HttpServletRequest servletRequest, String saveDir)throws IOException 
    {
    }  
}

2.在status2 .3.4.1版本下的struts.xml中的配置方式。其中class改为RequestParseWrapper类的路径就可以了,其他的不用动;蓝色部分就是不同之处。

type= "org.apache.struts2.dispatcher.multipart.MultiPartRequest"  name="myRequestParser" class= "com.s.RequestParseWrapper" scope= "default" optional= "true " /> 
"struts.multipart.handler" value= "myRequestParser" />

3.在status2 .3.15版本下的struts.xml中的配置方式。其中class改为RequestParseWrapper类的路径就可以了,其他的不用动

type= "org.apache.struts2.dispatcher.multipart.MultiPartRequest"  name="myRequestParser" class= "com.s.RequestParseWrapper" scope= "default" optional= "true " /> 
"struts.multipart.parser" value= "myRequestParser" />

4.在status2 .3.4.1版本和status2 .3.15下的struts.xml中的配置方式,除了标签中name不一样,其他的都一样,一个是struts.multipart.parser;另一个是struts.multipart.handler
可参考网站:https://my.oschina.net/guhai2004/blog/157852

4.在后台的控制器代码中可以加入以下代码

package com.qt.action;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.ExceptionMapping;
import org.apache.struts2.convention.annotation.ExceptionMappings;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import com.opensymphony.xwork2.ActionContext;
import com.qt.bean.appversionbean;
import com.qt.util.DBUtil;

@ParentPackage("admin-manager")
@Namespace("/MultiPartServlet")
@Results({ @Result(name = "success", location = "/WEB-INF/jsp/addApp.jsp") })
@ExceptionMappings({ @ExceptionMapping(exception = "java.lange.RuntimeException", result = "error") })
public class addApp extends BaseAction{
    private static final long serialVersionUID = -7531145953746024717L;

    //实体类
    public  appversionbean m=null;

    //存放后台输入的数据
    Map map =new HashMap();
    //返回的数据
    public String errMsg = "";
    //定义初始sql为空
    String sql ="";
    //定义变量ii,如果filename获取到了文件名称就会执行ii++,ii就会加一次,
    //ii=1代表页面在任何一个上传文件框中选择了一个文件,
    //ii>1代表选择了一个以上的文件进行上传  
    //ii=0代表页面没有在任何一个上传文件框中选择文件
    int ii=0;

    @Action("addApp")
    public String requestCount(){   
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet resultSet = null;

        //判断提交表单的类型是否为multipart/form-data,也可以做为是否为第一次进入这个页面
        boolean multipartContent = ServletFileUpload.isMultipartContent(getRequest());
        if(!multipartContent)  return SUCCESS;  
            try  
            { 
                //这个common-fileupload.jar的类,为后面使用数据使用
                DiskFileItemFactory factory=new DiskFileItemFactory();

                ServletFileUpload upload=new ServletFileUpload(factory);

                factory.setSizeThreshold(4096);// 内存存储的最大值 
                upload.setFileSizeMax(1024*1024*100);   // 设置上传的单个文件的最大字节数为100M 
                upload.setSizeMax(1024*1024*1024);   //设置整个表单的最大字节数为1G 

                upload.setHeaderEncoding("UTF-8");
                //通过该方法可以得到jsp中表单的所有的数据,以流的形式传入,如果该方法得到的是一个null,那可能原因就是struts.xml没有配置正确
                List list=upload.parseRequest(getRequest());
                //创建2个对象分别存入一样的数据是因为,it1是为了取非file数据,it2是取file数据,如果共用一个对象迭代了一次后再想迭代就不可以了
                Iterator it1=list.iterator();
                Iterator it2=list.iterator();
                //获取普通表单数据存入map集合中
                add_input_map(it1);

                //判断页面普通表单该输入的数据是否输入
                if (isDataEmpty(map)) {
                    return SUCCESS;
                }               

                //获取上传文件的表单数据,普通输入框和上传输入框的的文件都在这里面,需要一个一个的取,上传文件后并填充map值
                add_input_file_map(it2);    
                //判断页面是否在文件上传框中选择了上传的文件
                if(ii<1){
                 errMsg = "请选择一个上传文件!"; //上次文件不能为空!
                 return SUCCESS;
               }

                //查询出当前数据库最新版本的数据(取最新一条)
                sql = "SELECT appversion_id,the_server_app_name,app_name,url,version_number,app_state,app_type FROM j_appversion WHERE app_state=? AND app_type=? ORDER BY upload_time DESC LIMIT 1";
                conn = DBUtil.getConnection();
                pstmt=DBUtil.getPreparedStatement(conn, sql);
                pstmt.setString(1, map.get("app_state"));
                pstmt.setString(2, map.get("app_type"));
                resultSet=pstmt.executeQuery();
                if(resultSet.next()){
                    m=new appversionbean();
                    m.setAppversion_id(resultSet.getInt(1));
                    m.setThe_server_app_name(resultSet.getString(2));
                    m.setApp_name(resultSet.getString(3));
                    m.setUrl(resultSet.getString(4));
                    m.setVersion_number(resultSet.getString(5));
                    m.setApp_state(resultSet.getString(6));
                    m.setApp_type(resultSet.getString(7));                  
                }

                //判断数据库中是否有最新上传数据,并且判断当前输入的版本号只能是:  输入的版本号 ==数据库最新版本号+1
                //这里的判断是:如果输入的版本号 != 数据库最新版本号+1就进入          
                if( null!=m  && Integer.parseInt(map.get("version_number"))!=(Integer.parseInt(m.getVersion_number())+1)){
                    errMsg = "请输入正确的版本号,数据库当前版本号是为【"+m.getVersion_number()+"】,你只能输入版本号:"+(Integer.parseInt(m.getVersion_number())+1);
                    return SUCCESS;
                }
                //将map数据插入数据库表j_appversion
                sql = "INSERT INTO j_appversion(j_appversion.the_server_app_name,j_appversion.app_name,j_appversion.url,j_appversion.version_number,j_appversion.app_state,j_appversion.app_type,j_appversion.upload_time) VALUES('"
                        + map.get("the_server_app_name")
                        + "','"
                        + map.get("app_name")
                        + "','"
                        + map.get("url")
                        + "','"
                        + map.get("version_number")
                        + "','"
                        + map.get("app_state")
                        + "','"
                        + map.get("app_type")
                        + "','"
                        + map.get("upload_time")
                        + "')";
                pstmt = conn.prepareStatement(sql);
                pstmt.execute();
                errMsg = "上传成功!"; 
           }catch (Exception e) {
                errMsg = "上传失败!请联系管理员";
                return SUCCESS; 
           } finally {
                DBUtil.closeAll(conn, pstmt, resultSet);
           }
        return SUCCESS;
    }


    /**
     * 通过传入的从jsp页面获取到的数据,普通输入框和上传输入框的的文件都在这里面,需要一个一个的取,取出上传文件的数据后上传并填充剩余的map值
     * @param it
     * @param ii
     * @return
     * @throws FileNotFoundException
     * @throws IOException
     */
    public void add_input_file_map(Iterator it)
            throws FileNotFoundException, IOException {
        while(it.hasNext())
        {
            FileItem item=(FileItem)it.next();//每一个item就代表一个表单输出项(可能是普通输入框的数据,也可能是上传框的文件)

            if(!item.isFormField())//判断input是否为普通表单输入项还是上传框的文件,这里item.isFormField()为普通的输入框的数据返回true
            {
                //获取文件名称
                String filename=item.getName();
                if(!StringUtils.isEmpty(filename)){
                    //进入这个方法代表获取到了上传文件名称,即代表用户选择了上传文件,ii需要加一次
                    ii++;
                    //截取上传文件的名称的后缀(不带符号小数点".")
                    String prefix=filename.substring(filename.lastIndexOf(".")+1);

                    //得当当前时间格式是:yyyyMMddHHmmss
                    Date currentTime = new Date();   
                    SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");   
                    String dateString = formatter.format(currentTime);

                    //随机四位数产生(1000-9999的随机数)
                    int random_number=(int)(Math.random()*(9999-1000+1))+1000;
                    //重新对上传文件的名称进行更改,更改规则为:当前时间(年月日时分秒)+四位随机数+文件后缀名(不带符号小数点".")
                    String newfilename=dateString+random_number+"."+prefix;


                    //得到上传文件要写入的目录
                    ActionContext ac = ActionContext.getContext();     
                    ServletContext sc = (ServletContext) ac.get(ServletActionContext.SERVLET_CONTEXT);     
                    String  path = sc.getRealPath("/"); 
                    System.out.println(path);

                    FileOutputStream out=new FileOutputStream(path+"UploadFileStorage/"+newfilename);//如果文件目录无法自动创建就手动创建

                    //填充数据库表字段的数据
                    //1、代表安卓软件;2、代表类型为苹果软件
                    if("1".equals(map.get("app_state"))){
                        map.put("app_name", "安卓软件");
                    }else{
                        map.put("app_name", "苹果软件");
                    }
                    //下载路径
                    map.put("url", "UploadFileStorage/"+newfilename);
                    //上传到服务器上的app软件名称
                    map.put("the_server_app_name",newfilename);
                    //上传时间(获得当前时间格式yyyy-MM-dd HH:mm:ss)
                    formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");   
                    String upload_date = formatter.format(currentTime); 
                    map.put("upload_time",upload_date);
                    //上传到服务器上的app软件名称
                    map.put("the_server_app_name",newfilename);
                    //上传文件
                    InputStream in = item.getInputStream();
                    byte buffer[] = new byte[1024];
                    int len = 0;
                    while((len=in.read(buffer))>0){
                     out.write(buffer,0,len);
                    }
                    in.close();
                    out.close();
                 }
            }
          }
    }


    /**
     * 获取普通表单数据存入map集合中
     * @param it
     * @throws UnsupportedEncodingException
     */
    public void add_input_map(Iterator it)
            throws UnsupportedEncodingException {
        while(it.hasNext())
        {
            FileItem item=(FileItem)it.next();//每一个item就代表一个表单输出项

            if(item.isFormField())//判断input是否为普通表单输入项,这里item.isFormField()为普通的输入框的数据返回true
            {
                String name=item.getFieldName();//input的name名称

                String value= item.getString("UTF-8");//input的value值
                //存入页面普通表单输入项的数据
                map.put(name, value);
                System.out.println(name + "=" + value); 
            }else{

            }
        }
    }

    private boolean isDataEmpty(Map map) {  
        if (StringUtils.isEmpty(map.get("app_state"))){
            errMsg = "app软件类型不能为空!";
            return true;
        }
        if (StringUtils.isEmpty(map.get("app_type"))){
            errMsg = "app类别不能为空!";
            return true;
        }   
        if (StringUtils.isEmpty(map.get("version_number"))){
            errMsg = "版本号不能为空";
            return true;
        }       
        return false;
    }   
}

你可能感兴趣的:(java)