其实struts2的上传和下载和本系列关系不大,但是在架构搭建中,上传和下载是必然会遇到的。
而且能封装的自然封装,这样调用或者给其他程序员提供参考代码,将会大大缩短开发时间。
以前我写过上传和下载的功能,当时使用commons-fileupload-xxx.jar实现的。
struts2的上传和下载其实也是对这个包功能的封装,而且做得很好,使用很方便,包括对文件类型
和文件大小的限制都可以配置实现。所以考虑把它写到架构知识系列中。
在我的实例中,除了上传和下载,我还设计了一张保存文件信息的表(在实际中肯定会有这么一张表的)。
整个例子的代码我都做过实际测试,总体感觉还不错。
后面还设计到图片的上传和下载,把图片单拿出来,是因为图片在上传后和下载前需要有预览功能,
而且我打算在这个功能中实现把图片写入数据库的blob字段中。获取图片也是从数据库先获取,然后
在展示。这个功能设计到读写blob。所以放到下篇再讲。
本篇可能会用到以前写的工具类,在这就不保证全部贴出了,那个不影响整体功能的。
看看效果:
对错误的提示功能:
--------------------------------------------------------------------------------------------------------------------------------------------
大小超过限制:
文件类型不符合要求:
##################################################################
1,数据库设计file_vo表结构脚本.sql
/*
SQLyog 企业版 - MySQL GUI v7.14
MySQL - 5.1.57-community : Database - myact
*********************************************************************
*/
/*!40101 SET NAMES utf8 */;
/*!40101 SET SQL_MODE=''*/;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`myact` /*!40100 DEFAULT CHARACTER SET utf8 */;
USE `myact`;
/*Table structure for table `file_vo` */
DROP TABLE IF EXISTS `file_vo`;
CREATE TABLE `file_vo` (
`file_id` varchar(32) NOT NULL COMMENT '主键',
`file_name` varchar(150) DEFAULT NULL COMMENT '名称,例a.txt',
`file_suffix` varchar(32) DEFAULT NULL COMMENT '后缀,例.txt',
`file_webpath` varchar(200) DEFAULT NULL COMMENT '在webapp下的路径,例tempfiles/upload',
`file_phydir` varchar(150) DEFAULT NULL COMMENT '在物理硬盘上的路径,例D:\\app',
`file_size` varchar(32) DEFAULT NULL COMMENT '文件大小,单位KB',
`file_contenttype` varchar(150) DEFAULT NULL COMMENT '文件contenttype',
`foreign_key_id` varchar(32) DEFAULT NULL COMMENT '和其他表关联的id',
`create_time` varchar(32) DEFAULT NULL COMMENT '创建时间',
`last_edit_time` varchar(32) DEFAULT NULL COMMENT '最后更改时间',
`creator` varchar(150) DEFAULT NULL COMMENT '创建人',
`owner_id` varchar(150) DEFAULT NULL COMMENT '拥有人',
`isvalid` varchar(10) DEFAULT NULL COMMENT '是否有效(1有效,0无效)',
`imagedata` longblob COMMENT '图片数据',
`bigtextdata` longtext COMMENT '大文本数据',
`bak1` varchar(200) DEFAULT NULL COMMENT '未定用途1',
`bak2` varchar(200) DEFAULT NULL COMMENT '未定用途2',
PRIMARY KEY (`file_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
FileVo:
package org.act.upload.bean;
import java.sql.Blob;
import java.sql.Clob;
//import com.mysql.jdbc.Blob;
//import com.mysql.jdbc.Clob;
public class FileVo {
private String file_id;
private String file_name;
private String file_suffix;
private String file_webpath;
private String file_phydir;
private String file_size;
private String file_contenttype;
private String foreign_key_id;
private String create_time;
private String last_edit_time;
private String creator;
private String owner_id;
private String isvalid;
private Blob imagedata;
private Clob bigtextdata;
private String bak1; //备用字段
private String bak2;
public String getFile_id() {
return file_id;
}
public void setFile_id(String file_id) {
this.file_id = file_id;
}
public String getFile_name() {
return file_name;
}
public void setFile_name(String file_name) {
this.file_name = file_name;
}
public String getFile_suffix() {
return file_suffix;
}
public void setFile_suffix(String file_suffix) {
this.file_suffix = file_suffix;
}
public String getFile_webpath() {
return file_webpath;
}
public void setFile_webpath(String file_webpath) {
this.file_webpath = file_webpath;
}
public String getFile_phydir() {
return file_phydir;
}
public void setFile_phydir(String file_phydir) {
this.file_phydir = file_phydir;
}
public String getFile_size() {
return file_size;
}
public void setFile_size(String file_size) {
this.file_size = file_size;
}
public String getFile_contenttype() {
return file_contenttype;
}
public void setFile_contenttype(String file_contenttype) {
this.file_contenttype = file_contenttype;
}
public String getForeign_key_id() {
return foreign_key_id;
}
public void setForeign_key_id(String foreign_key_id) {
this.foreign_key_id = foreign_key_id;
}
public String getCreate_time() {
return create_time;
}
public void setCreate_time(String create_time) {
this.create_time = create_time;
}
public String getLast_edit_time() {
return last_edit_time;
}
public void setLast_edit_time(String last_edit_time) {
this.last_edit_time = last_edit_time;
}
public String getCreator() {
return creator;
}
public void setCreator(String creator) {
this.creator = creator;
}
public String getOwner_id() {
return owner_id;
}
public void setOwner_id(String owner_id) {
this.owner_id = owner_id;
}
public String getIsvalid() {
return isvalid;
}
public void setIsvalid(String isvalid) {
this.isvalid = isvalid;
}
public Blob getImagedata() {
return imagedata;
}
public void setImagedata(Blob imagedata) {
this.imagedata = imagedata;
}
public Clob getBigtextdata() {
return bigtextdata;
}
public void setBigtextdata(Clob bigtextdata) {
this.bigtextdata = bigtextdata;
}
@Override
public String toString() {
return "FileVo [file_id=" + file_id + ", file_name=" + file_name
+ ", file_suffix=" + file_suffix + ", file_webpath="
+ file_webpath + ", file_phydir=" + file_phydir
+ ", file_size=" + file_size + ", file_contenttype="
+ file_contenttype + ", foreign_key_id=" + foreign_key_id
+ ", create_time=" + create_time + ", last_edit_time="
+ last_edit_time + ", creator=" + creator + ", owner_id="
+ owner_id + ", isvalid=" + isvalid + ", imagedata="
+ imagedata + ", bigtextdata=" + bigtextdata
+ ", getFile_id()=" + getFile_id() + ", getFile_name()="
+ getFile_name() + ", getFile_suffix()=" + getFile_suffix()
+ ", getFile_webpath()=" + getFile_webpath()
+ ", getFile_phydir()=" + getFile_phydir()
+ ", getFile_size()=" + getFile_size()
+ ", getFile_contenttype()=" + getFile_contenttype()
+ ", getForeign_key_id()=" + getForeign_key_id()
+ ", getCreate_time()=" + getCreate_time()
+ ", getLast_edit_time()=" + getLast_edit_time()
+ ", getCreator()=" + getCreator() + ", getOwner_id()="
+ getOwner_id() + ", getIsvalid()=" + getIsvalid()
+ ", getImagedata()=" + getImagedata() + ", getBigtextdata()="
+ getBigtextdata() + ", getClass()=" + getClass()
+ ", hashCode()=" + hashCode() + ", toString()="
+ super.toString() + "]";
}
public String getBak1() {
return bak1;
}
public void setBak1(String bak1) {
this.bak1 = bak1;
}
public String getBak2() {
return bak2;
}
public void setBak2(String bak2) {
this.bak2 = bak2;
}
}
FileVo.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.act.upload.bean.FileVo" table="file_vo" >
<id name="file_id" type="java.lang.String">
<column name="file_id" length="32" />
<generator class="assigned" />
</id>
<property name="file_name" type="java.lang.String">
<column name="file_name" length="150" />
</property>
<property name="file_suffix" type="java.lang.String">
<column name="file_suffix" length="32" />
</property>
<property name="file_webpath" type="java.lang.String">
<column name="file_webpath" length="200" />
</property>
<property name="file_phydir" type="java.lang.String">
<column name="file_phydir" length="150" />
</property>
<property name="file_size" type="java.lang.String">
<column name="file_size" length="32" />
</property>
<property name="file_contenttype" type="java.lang.String">
<column name="file_contenttype" length="150" />
</property>
<property name="foreign_key_id" type="java.lang.String">
<column name="foreign_key_id" length="32" />
</property>
<property name="create_time" type="java.lang.String">
<column name="create_time" length="32" />
</property>
<property name="last_edit_time" type="java.lang.String">
<column name="last_edit_time" length="32" />
</property>
<property name="creator" type="java.lang.String">
<column name="creator" length="150" />
</property>
<property name="owner_id" type="java.lang.String">
<column name="owner_id" length="150" />
</property>
<property name="isvalid" type="java.lang.String">
<column name="isvalid" length="10" />
</property>
<property name="imagedata" type="java.sql.Blob">
<column name="imagedata"/>
</property>
<property name="bigtextdata" type="java.sql.Clob">
<column name="bigtextdata"/>
</property>
<property name="bak1" type="java.lang.String">
<column name="bak1" length="200" />
</property>
<property name="bak2" type="java.lang.String">
<column name="bak2" length="200" />
</property>
</class>
</hibernate-mapping>
2,spring配置,以及dao方法。
context_upload.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<bean id="fileDao" parent="transactionProxyTemplate">
<property name="target">
<bean class="org.act.upload.dao.impl.FileDaoImpl">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
</property>
<property name="proxyInterfaces">
<value>org.act.upload.dao.FileDao</value>
</property>
</bean>
</beans>
FileDao.java
package org.act.upload.dao;
import java.util.List;
import org.act.upload.bean.FileVo;
public interface FileDao {
public List queryFile(String file_name);
public FileVo queryFileById(String file_id);
public void addFileVo(FileVo vo);
}
FileDaoImpl.java
package org.act.upload.dao.impl;
import java.util.List;
import org.act.upload.bean.FileVo;
import org.act.upload.dao.FileDao;
import org.base.MyHibernateDao;
public class FileDaoImpl extends MyHibernateDao implements FileDao{
public List queryFile(String file_name) {
List list=null;
if(file_name==null||file_name.trim().equals("")){
System.out.println("参数file_name为空,查询所有值。");
String hql="from FileVo";
list=this.queryListHql(hql);
}else{
String hql="from FileVo f where f.file_name like '%"+file_name.trim()+"%'";
list=this.queryListHql(hql);
}
return list;
}
public FileVo queryFileById(String file_id) {
FileVo vo=new FileVo();
List list=null;
if(file_id==null||file_id.trim().equals("")){
System.out.println("参数file_id为空!");
}else{
String hql="from FileVo f where f.file_id='"+file_id.trim()+"'";
list=this.queryListHql(hql);
if(list!=null){
vo=(FileVo)list.get(0);
}
}
return vo;
}
public void addFileVo(FileVo vo){
if(vo!=null){
this.saveHql(vo);
}
}
}
3,struts配置以及action(注意struts是重点!)
struts_upload.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.i18n.encoding" value="utf8" />
<package name="file" namespace="/file" extends="struts-default">
<!-- 使用struts2标签和拦截器实现上传 -->
<action name="goUploadStruts">
<result>/jsp/upload/upload_struts.jsp</result>
</action>
<action name="uploadStruts" class="org.act.upload.action.UploadAction">
<result name="input">/jsp/upload/upload_struts.jsp</result>
<result name="error">/jsp/upload/upload_struts_error.jsp</result>
<result name="success">/jsp/upload/download_struts.jsp</result>
<interceptor-ref name="fileUpload">
<!--单个文件允许的大小 单位是比特B(1M=1024KB;1KB=1024B),10M=10*1024*1024=10485760 -->
<param name="maximumSize">10485760</param>
<!-- 允许上传的文件类型,可以到Tomcat_home/conf下的web.xml文件中找到所有文件类型的类型名,逗号隔开 -->
<param name="allowedTypesSet">
application/vnd.ms-excel,text/plain,image/png,application/pdf
,image/x-portable-bitmap,audio/x-mpeg,image/jpeg,text/plain,application/java-archive,text/html,image/gif,application/msword
</param>
<!-- application/zip,容许文件类型分别为zip,xls,txt,png,pdf,pbm,mp3,jpg,java,jar,html,gif,doc -->
<!-- application/octet-stream 对应exe-->
</interceptor-ref>
<interceptor-ref name="defaultStack" />
</action>
<action name="downloadFile" class="org.act.upload.action.DownloadAction">
<result name="success" type="stream">
<param name="contentDisposition">attachment;filename="${fileName}"</param>
<!-- 获取InputStream的get方法 -->
<param name="inputName">inputStreamOfFile</param>
<!-- 下载文件的缓冲大小 -->
<param name="bufferSize">4096</param>
</result>
</action>
<!-- 业务上的查询 -->
<action name="queryById" class="org.act.upload.action.QueryFileAction" method="queryById">
<result name="success">/jsp/upload/download_struts.jsp</result>
</action>
<action name="queryByName" class="org.act.upload.action.QueryFileAction">
<result name="success">/jsp/upload/download_struts.jsp</result>
</action>
</package>
</struts>
上传 UploadAction
package org.act.upload.action;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import oracle.sql.BLOB;
import org.act.upload.bean.FileVo;
import org.act.upload.dao.FileDao;
import org.apache.commons.io.FileUtils;
import org.apache.struts2.ServletActionContext;
import org.base.MyBaseAction;
import org.base.pk.UUIDHexGenerator;
import org.base.util.DateUtil;
import org.base.util.PropertiesUtil;
import org.hibernate.Hibernate;
import com.opensymphony.xwork2.ActionSupport;
/**
* 使用struts2实现上传
* @author lushuaiyin
*
*/
public class UploadAction extends MyBaseAction {
private static final long serialVersionUID = 1L;
private File[] upload;// 上传文件
private String[] uploadContentType; // 文件的内容类型
private String[] uploadFileName; // 上传文件名
private FileDao fileDao;
public String execute() throws Exception {
try {
String defPath="";
defPath=(PropertiesUtil.readProperty("uploadFilePath")==null||PropertiesUtil.readProperty("uploadFilePath").trim().equals(""))?"":
PropertiesUtil.readProperty("uploadFilePath").trim();
String targetDirectory = ServletActionContext.getServletContext().getRealPath(File.separator + defPath);// 获得路径
for (int i = 0; i < upload.length; i++) {
FileVo vo=new FileVo();
String fileName = uploadFileName[i];// 上传的文件名
String type = uploadContentType[i];// 文件类型//application/x-zip-compressed
String id = (String) UUIDHexGenerator.generate();//产生主键id
String fileSuffix=getFileSuffix(fileName);//后缀
String idName = id+getFileSuffix(fileName);// 主键id+文件的后缀
File target = new File(targetDirectory, idName);
FileUtils.copyFile(upload[i], target);//上传文件到服务器
//这里一般也需要写库,记录文件的一些信息。如果是图片,根据需要可以写入blob
//vo写库
vo.setFile_id(id);
vo.setFile_name(fileName);
vo.setFile_suffix(fileSuffix);
String webpath=defPath+"/"+id+fileSuffix;
vo.setFile_webpath(webpath);
vo.setFile_phydir(targetDirectory);
Long size=upload[i].length();
Double dsize=new Double(size);
vo.setFile_size(String.valueOf(dsize/1024));//单位KB
vo.setFile_contenttype(type);
String nowTime=DateUtil.getDateStrWithSecond();
vo.setCreate_time(nowTime);
vo.setLast_edit_time(nowTime);
String userId=this.getHttpSession().getAttribute("userId")!=null?(String)this.getHttpSession().getAttribute("userId"):"";
vo.setCreator(userId);
vo.setOwner_id(userId);
vo.setIsvalid("1");
// vo.setImagedata(BLOB.empty_lob());
vo.setImagedata(Hibernate.createBlob(new byte[0]));
vo.setBigtextdata(Hibernate.createClob(""));
System.out.println(vo.toString());
fileDao.addFileVo(vo);
}
} catch (Exception e) {
e.printStackTrace();
addActionError(e.getMessage());
return INPUT;
}
return SUCCESS;
}
public File[] getUpload() {
return upload;
}
public void setUpload(File[] upload) {
this.upload = upload;
}
public String[] getUploadContentType() {
return uploadContentType;
}
public void setUploadContentType(String[] uploadContentType) {
this.uploadContentType = uploadContentType;
}
public String[] getUploadFileName() {
return uploadFileName;
}
public void setUploadFileName(String[] uploadFileName) {
this.uploadFileName = uploadFileName;
}
//获取文件后缀
public static String getFileSuffix(String fileName) {
return fileName.substring(fileName.lastIndexOf(".")).trim();
}
public FileDao getFileDao() {
return fileDao;
}
public void setFileDao(FileDao fileDao) {
this.fileDao = fileDao;
}
}
查询列表QueryFileAction
package org.act.upload.action;
import java.util.List;
import org.act.upload.dao.FileDao;
import org.apache.struts2.ServletActionContext;
import org.base.MyBaseAction;
import org.act.upload.bean.FileVo;
/**
* 文件的查询
* @author lushuaiyin
*
*/
public class QueryFileAction extends MyBaseAction {
private static final long serialVersionUID = 1L;
private FileDao fileDao;
public String execute() throws Exception {
String filename = ServletActionContext.getRequest().getParameter("filename");
List fileList=fileDao.queryFile(filename);
ServletActionContext.getRequest().setAttribute("fileList", fileList);
return SUCCESS;
}
public String queryById() throws Exception {
String file_id = ServletActionContext.getRequest().getParameter("file_id");
if(file_id==null||file_id.trim().equals("")){
System.out.println("未获取到文件参数!");
}else{
FileVo fileVO=null;
if(fileDao.queryFileById(file_id)!=null){
fileVO=fileDao.queryFileById(file_id);
ServletActionContext.getRequest().setAttribute("fileVO", fileVO);
}
}
return SUCCESS;
}
public FileDao getFileDao() {
return fileDao;
}
public void setFileDao(FileDao fileDao) {
this.fileDao = fileDao;
}
}
下载DownloadAction(注意和struts配置项对应)
package org.act.upload.action;
import java.io.InputStream;
import org.act.upload.bean.FileVo;
import org.act.upload.dao.FileDao;
import org.apache.struts2.ServletActionContext;
import org.base.util.PropertiesUtil;
import com.opensymphony.xwork2.ActionSupport;
/**
* 下载文件
* @author lushuaiyin
*
*/
public class DownloadAction extends ActionSupport {
private static final long serialVersionUID = 1L;
private String fileName;//文件的实际名称(上传前的名称),供下载时弹出框使用
private String fileWebName;//在服务器上存放的实际名称 (我使用的是id+文件实际后缀)
private FileDao fileDao;
private FileVo fileVO;
public void setFileName() {
this.fileName = getFileVO().getFile_name();
}
/**
* 获取文件下载时的名称,在弹出框里使用。
* 在struts配置文件中指定了<param name="contentDisposition">attachment;filename="${fileName}"</param>
* 所以会调用getFileName()方法
* @return
*/
public String getFileName(){
return getFileVO().getFile_name();
}
/**
* 获取下载流。在struts配置文件中指定了<param name="inputName">inputStreamOfFile</param>
* 所以会调用getInputStreamOfFile()方法
* @return
*/
public InputStream getInputStreamOfFile() {
String defPath=(PropertiesUtil.readProperty("uploadFilePath")==null||PropertiesUtil.readProperty("uploadFilePath").trim().equals(""))?"":
PropertiesUtil.readProperty("uploadFilePath").trim();
String filepath="/" + defPath + "/" + getFileWebName();
return ServletActionContext.getServletContext().getResourceAsStream(filepath);
}
//在服务器上存放的实际名称
public String getFileWebName() {
return getFileVO().getFile_id().trim()+getFileVO().getFile_suffix().trim();
}
public void setFileWebName() {
this.fileWebName = getFileVO().getFile_id().trim()+getFileVO().getFile_suffix().trim();;
}
@Override
public String execute() throws Exception {
//在请求下载时,程序先走execute方法,这样我们先给FileVO赋值;开始下载后,拦截器需要知道文件名和文件类型(在struts文件中param配置从哪个方法获取)
//这样拦截器会从指定的方法中获取文件流,文件名,文件类型。
System.out.println("hereeeeeeeeeeeeeeeeeeeeeeeeeee");
String file_id = ServletActionContext.getRequest().getParameter("file_id");
if(file_id==null||file_id.trim().equals("")){
System.out.println("未获取到文件参数!");
}else{
this.setFileVO(fileDao.queryFileById(file_id));
}
return SUCCESS;
}
public FileDao getFileDao() {
return fileDao;
}
public void setFileDao(FileDao fileDao) {
this.fileDao = fileDao;
}
public FileVo getFileVO() {
return fileVO;
}
public void setFileVO(FileVo fileVO) {
this.fileVO = fileVO;
}
}
4,配置上传路径
这个写到resource.properties中了,你可以把这个写死
#uploadFilePath is under webapp
uploadFilePath=tempfiles/upload
5,jsp页面
这部分其实有个上传多个文件的逻辑实现。本人用jquery实现的(见上图中可以多文件上传),写的很粗糙,不错效果还是不错。
上传页面upload_struts.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<%@page import="java.util.*"%>
<%
String path = request.getContextPath();
%>
<html>
<head>
<meta name="author" content="lushuaiyin">
<meta name="description" content="http://blog.csdn.net/lushuaiyin">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>uploadFile</title>
<link rel="stylesheet" type="text/css" href="<%=path%>/resource/css/table.css" />
<script src="<%=path%>/script/jquery-1.7.1.min.js" type="text/javascript"></script>
</head>
<body>
<table align="center" width="80%" height="120px">
<tr>
<td>
采用stuts2标签和拦截器实现
</td>
</tr>
<tr>
<td>
<s:fielderror cssStyle="color:green" />
<s:actionmessage cssStyle="color:blue" />
<s:actionerror cssStyle="color:red" />
</td>
</tr>
</table>
<s:form id="form1" name="form1" action="/file/uploadStruts.action" theme="simple" method="post"
enctype="multipart/form-data">
<table id="mytable1" align="center" width="80%" class="table1" style="border-bottom-style:none">
<tr>
<td>
上传文件
</td>
<td>
<input type="file" name="upload" value="" />
</td>
<td>
<input type="button" value="继续添加文件" οnclick="addFile(this)">
</td>
</tr>
</table>
<table align="center" width="80%" class="table1" style="border-top-style:none">
<tr>
<td>
<input type="button" value="确认" οnclick="tijiao()">
</td>
<td>
</td>
<td>
<input type="button" value="重置" οnclick="clearAll()">
</td>
</tr>
</table>
</s:form>
</body>
</html>
<script type="text/javascript">
function addFile(td){
var tbody=$(td).parent().parent().parent().parent();
var tdp=$(td).parent().parent();
var v1=$(tdp).children()[1];
var inputfile=$(v1).children()[0];
if(inputfile.value==null||inputfile.value==''){
alert("请选择文件!");
}else{
//alert(vfile2.outerHTML);
var tdbutton=$(tdp).children().last();//已有的tr这一行需要把button清除
$(tdbutton).html("");
//添加新的一行
var htmlStr="<tr><td>上传文件</td><td><input type=\"file\" name=\"upload\" value=\"\" /></td>"
+"<td><input type=\"button\" value=\"继续上传\" οnclick=\"addFile(this)\"></td></tr>";
$(tbody).append(htmlStr);
}
}
function clearAll(){
var htmlStr="<tr><td>上传文件</td><td><input type=\"file\" name=\"upload\" value=\"\" /></td>"
+"<td><input type=\"button\" value=\"继续上传\" οnclick=\"addFile(this)\"></td></tr>";
$("#mytable1").html(htmlStr);
}
function tijiao(){
var size=$(":file").size();
var errorNumber=0;
$(":file").each(function(i){
//alert(this.value);
if(this.value==null||this.value==''){
errorNumber++;
}
});
if(errorNumber>=1){
alert("请选择一个文件!");
}else{
alert("开始上传...");
var form1=$("#form1");
form1.action="<%=path%>/file/uploadStruts.action";
$("#form1").submit();
}
}
</script>
upload_struts_error.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<%@page import="java.util.*"%>
<%
String path = request.getContextPath();
%>
<html>
<head>
<meta name="author" content="lushuaiyin">
<meta name="description" content="http://blog.csdn.net/lushuaiyin">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>uploadFile</title>
<link rel="stylesheet" type="text/css" href="<%=path%>/resource/css/table.css" />
<script src="<%=path%>/script/jquery-1.7.1.min.js" type="text/javascript"></script>
</head>
<body>
<table align="center" width="80%">
<tr>
<td>
采用stuts2标签和拦截器实现,错误原因:
</td>
</tr>
<tr>
<td>
<s:fielderror cssStyle="color:red" />
<s:actionmessage/>
<s:actionerror/>
</td>
</tr>
</table>
</body>
</html>
下载页面download_struts.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page import="java.util.*"%>
<%@ page import="org.act.upload.bean.FileVo"%>
<%
String path = request.getContextPath();
%>
<%
List list=null;
if(request.getAttribute("fileList")!=null){
list=(List)request.getAttribute("fileList");
}
%>
<html>
<head>
<meta name="author" content="lushuaiyin">
<meta name="description" content="http://blog.csdn.net/lushuaiyin">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>uploadFile</title>
<link rel="stylesheet" type="text/css" href="<%=path%>/resource/css/table.css" />
<script src="<%=path%>/script/jquery-1.7.1.min.js" type="text/javascript"></script>
</head>
<body>
<input type="hidden" value="<%=path%>" id="path">
<table align="center" width="80%" class="table2">
<tr>
<td>文件名:</td>
<td><input id="filename" name="filename" type="text" value="" /></td>
</tr>
<tr>
<td><input type="button" value="查询" οnclick="chaxunfile()"/></td>
<td><input type="button" value="取消" οnclick="javascript:filename.value=''"/></td>
</tr>
</table>
<table id="mytable1" align="center" width="80%" class="table1">
<tr>
<th></th>
<th>文件名</th>
<th>文件contenttype</th>
<th>大小(单位KB)</th>
<th>操作</th>
</tr>
<%
if(list!=null){
for(int i=0;i<list.size();i++){
FileVo vo=(FileVo)list.get(i);
String file_id="",file_name="",file_contenttype="",file_size="";
file_id=vo.getFile_id()==null?"":vo.getFile_id().trim();
file_name=vo.getFile_name()==null?"":vo.getFile_name().trim();
file_contenttype=vo.getFile_contenttype()==null?"":vo.getFile_contenttype().trim();
file_size=vo.getFile_size()==null?"0":vo.getFile_size().trim();
if(i%2==0){
%>
<tr class="interval">
<td><input type="hidden" value="<%=file_id%>" id="<%=file_id%>"></td>
<td><%=file_name%></td>
<td><%=file_contenttype%></td>
<td><%=file_size%></td>
<td><a href="javascript:void(0)" οnclick="downloadfile('<%=file_id%>')">下载文件</a></td>
</tr>
<%
}else{
%>
<tr>
<td><input type="hidden" value="<%=file_id%>" id="<%=file_id%>"></td>
<td><%=file_name%></td>
<td><%=file_contenttype%></td>
<td><%=file_size%></td>
<td><a href="javascript:void(0)" οnclick="downloadfile('<%=file_id%>')">下载文件</a></td>
</tr>
<%
}
}
}
%>
</table>
</body>
</html>
<script type="text/javascript">
var path=document.getElementById("path").value;
//下载文件
function downloadfile(file_id){
var url=path+"/file/downloadFile.action?file_id="+file_id;
window.location.href=url;
}
function queryById(file_id){
var url=path+"/file/queryById.action?file_id="+file_id;
window.location.href=url;
}
function chaxunfile(){
var filename=document.getElementById("filename").value;
var url=path+"/file/queryByName.action?filename="+filename;
window.location.href=url;
}
</script>
############
注意:
关于上传是struts2拦截器判断是否符合上传条件的返回信息。
(本例在做测试时,把zip类型从拦截器去掉)
如果是文件类型不符合要求,返回的信息需要使用标签
<s:fielderror cssStyle="color:green" />
如果是文件大小不符合要求,返回的信息需要使用标签
<s:actionmessage cssStyle="color:blue" />
或
<s:actionerror cssStyle="color:red" />
在上传页面,其实用不用struts的form和file标签(或者其他的标签)都无所谓。
使用原生的html也可以的。但是对于拦截器返回的错误信息,就必须使用
struts2的自定义标签。否则你是回去不到错误信息的。
值得注意的是,我在实际中没有配置exe类型,按理说应该被拦截器拦截的,应该有错误信息提示的。
但是实际结果却是能正常上传!这个原因还是没找到,具体在使用的时候,不能盲目相信文档,还是要自己亲自做测试才行。
网上搜了下,见对文件类型限制有使用allowedTypes这个参数的,我改成这个参数后,可以正常限制不符合要求的文件类型。
也有说还可以换成allowedExtensions,我试了下,和allowedTypesSet一样,没起作用。原因只能看源码了。
上面struts配置文件struts_upload.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.i18n.encoding" value="utf8" />
<package name="file" namespace="/file" extends="struts-default">
<!-- 使用struts2标签和拦截器实现上传 -->
<action name="goUploadStruts">
<result>/jsp/upload/upload_struts.jsp</result>
</action>
<action name="uploadStruts" class="org.act.upload.action.UploadAction">
<result name="input">/jsp/upload/upload_struts.jsp</result>
<result name="error">/jsp/upload/upload_struts_error.jsp</result>
<result name="success">/jsp/upload/download_struts.jsp</result>
<interceptor-ref name="fileUpload">
<!--单个文件允许的大小 单位是比特B(1M=1024KB;1KB=1024B),10M=10*1024*1024=10485760 -->
<param name="maximumSize">10485760</param>
<!-- 允许上传的文件类型,可以到Tomcat_home/conf下的web.xml文件中找到所有文件类型的类型名,逗号隔开 application/vnd.ms-excel, -->
<!--
<param name="allowedTypesSet">
text/plain,image/png,application/pdf
,image/x-portable-bitmap,audio/x-mpeg,image/jpeg,text/plain,application/java-archive,text/html,image/gif,application/msword
</param>
-->
<!-- application/zip,容许文件类型分别为zip,xls,txt,png,pdf,pbm,mp3,jpg,java,jar,html,gif,doc -->
<!-- application/octet-stream 对应exe-->
<!-- 允许上传的文件类型,可以到Tomcat_home/conf下的web.xml文件中找到所有文件类型的类型名,逗号隔开 application/vnd.ms-excel, -->
<param name="allowedTypes">
text/plain,image/png,application/pdf
,image/x-portable-bitmap,audio/x-mpeg,image/jpeg,text/plain,application/java-archive,text/html,image/gif,application/msword
</param>
<!-- application/zip,容许文件类型分别为zip,xls,txt,png,pdf,pbm,mp3,jpg,java,jar,html,gif,doc -->
<!-- application/octet-stream 对应exe-->
<!-- 允许后缀名为png,bmp,jpg,doc,xls的文件上传 -->
<!--
<param name="allowedExtensions">
png,bmp,jpg,doc,xls
</param>
-->
</interceptor-ref>
<interceptor-ref name="defaultStack" />
</action>
<action name="downloadFile" class="org.act.upload.action.DownloadAction">
<result name="success" type="stream">
<param name="contentDisposition">attachment;filename="${fileName}"</param>
<!-- 获取InputStream的get方法 -->
<param name="inputName">inputStreamOfFile</param>
<!-- 下载文件的缓冲大小 -->
<param name="bufferSize">4096</param>
</result>
</action>
<!-- 业务上的查询 -->
<action name="queryById" class="org.act.upload.action.QueryFileAction" method="queryById">
<result name="success">/jsp/upload/download_struts.jsp</result>
</action>
<action name="queryByName" class="org.act.upload.action.QueryFileAction">
<result name="success">/jsp/upload/download_struts.jsp</result>
</action>
</package>
</struts>