您的位置:首页 > 移动开发

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

2017-01-21 10:22 681 查看
一:框架信息

只使用了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类的路径就可以了,其他的不用动;蓝色部分就是不同之处。

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


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

<bean type= "org.apache.struts2.dispatcher.multipart.MultiPartRequest"  name="myRequestParser" class= "com.s.RequestParseWrapper" scope= "default" optional= "true " />
<constant name= "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<String, String> map =new HashMap<String, String>();
//返回的数据
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<FileItem> list=upload.parseRequest(getRequest());
//创建2个对象分别存入一样的数据是因为,it1是为了取非file数据,it2是取file数据,如果共用一个对象迭代了一次后再想迭代就不可以了
Iterator<FileItem> it1=list.iterator();
Iterator<FileItem> 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<FileItem> 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<FileItem> 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<String, String> 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;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息