文件上传需要具备以下几个条件:
客户端:
- Form表单必须指定Mime协议为:enctype=”multipart/form-data”,即采用多媒体表单数据编码;
- Form表单请求方式必须为post;
- Form表单中必须有文本框,必须提供name属性。
服务端:
- JavaWeb:Apache commons-fileupload工具包实现上传;
- Struts2:提供了FileUploadInterceptor拦截器,将Apache commons-fileupload进行了封装,使用更简单。
上述客户端在上传的时候,先浏览文件,将文件路径存入表单,然后再通过form表单提交,将其提交到服务端。
为提升用户体验(UE),现在的系统流行一键上传,即用户点击了上传按钮或链接后,直接选择要上传的文件,点击确定就开始上传了,无需额外提交表单。而且页面无刷新。
Ocupload即One-click upload,一键上传。
插件下载:http://code.google.com/p/ocupload
插件的使用:
官方示例:
$(element).upload({
name: 'file',//上传组件的name属性,即
action: '',//向服务器请求的路径
enctype: 'multipart/form-data',//mime类型,默认即可
params: {},//请求时额外传递的参数,默认为空
autoSubmit: true,//是否自动提交,即当选择了文件,自动关闭了选择窗口后,是否自动提交请求。
onSubmit: function() {},//提交表单之前触发事件
onComplete: function() {},//提交表单完成后触发的事件
onSelect: function() {}//当用户选择了一个文件后触发事件
});
开发代码:
//给导入按钮绑定一键上传插件
$("#button-import").upload({
name: 'upload',//上传组件的name属性,即
action: '${pageContext.request.contextPath}/region_importData.action',//向服务器请求的路径
onComplete: function(response) {//提交表单完成后触发的事件
//response是响应后放到页面的一个json'字符串,不是json对象
//转换为json对象
var data =eval("("+response+")");
if(data.result){
$.messager.alert("信息","文件上传成功","info");
}else{
$.messager.alert("错误","文件上传失败","error");
}
},
onSelect: function() {//当用户选择了一个文件后触发事件
//当选择了文件后,关闭自动提交
this.autoSubmit=false;
//校验上传的文件名是否满足后缀为.xls或.xlsx
//var regex =/^.*\.(?:xls|xlsx)$/;
var regex =/^.*\.xlsx?$/i;
//this.filename()返回当前选择的文件名称
if(regex.test(this.filename())){
//通过校验
this.submit();
}else{
//未通过
$.messager.alert("警告","文件格式不正确,必须以.xls或xlsx结尾","warning")
}
}
});
使用fileUpload拦截器:
[File Name] : File - the actual File
[File Name]ContentType : String - the content type of the file
[File Name]FileName : String - the actual name of the file uploaded (not the HTML name)
Java界常见的解析Excel文档的开源项目有两种:Apache POI和 JXL。
POI的功能可以解析微软的Office组件的文档格式。
企业中通常使用其解析Excel文档或生成Excel文档(SS)。
POI支持HSSF解析(.xls–Excel97-2007之前版本,仅支持65535行记录)和XSSF解析(.xlsx–Excel2007及以后版本)。
一. 使用Maven的坐标引入POI(根据需要可以引入HSSF和XSSF的):
<poi.version>3.9poi.version>
<dependency>
<groupId>org.apache.poigroupId>
<artifactId>poiartifactId>
<version>${poi.version}version>
dependency>
<dependency>
<groupId>org.apache.poigroupId>
<artifactId>poi-ooxmlartifactId>
<version>${poi.version}version>
dependency>
二. 编写解析Excel的代码。
POI解析的基本过程:打开WorkBook工作簿文件—》找到Sheet工作表—》遍历读取Rows行—》读取行中的cell单元格。
@ParentPackage("basicstruts2")
@Controller("regionAction")
@Scope("prototype")
@Namespace("/")
public class RegionAction extends BaseAction<Region> {
//上传文件属性
private File upload;//上传的文件,名字必须和表单的name属性一致
private String uploadFileName;//文件名
private String uploadContextType;//文件类型
public void setUpload(File upload) {
this.upload = upload;
}
public void setUploadFileName(String uploadFileName) {
this.uploadFileName = uploadFileName;
}
public void setUploadContextType(String uploadContextType) {
this.uploadContextType = uploadContextType;
}
//注入service
@Autowired
private RegionService regionService;
/**
* 区域文件上传
* @return
* @throws Exception
*/
@Action(value="region_upload",,results={@Result(name=JSON,type=JSON)})
public String upload()throws Exception{
//获取客户端上传的文件(使用属性驱动+fileUpload拦截器)
//存放结果集map
Map resultMap = new HashMap();
//存放region的list
List regionList = new ArrayList();
try {
//解析excel
//1.读取文件输入流
InputStream is = new FileInputStream(upload);
//2.创建Excel工作簿文件(包含.xsl和.xslx格式)
Workbook wb = WorkbookFactory.create(is);
//3.打开需要解析的Sheet工作表
Sheet sheet = wb.getSheetAt(0);
//4.遍历工作表对象(本质是个行的集合),读取每一行
for (Row row : sheet) {
//跳过第一行
if (row.getRowNum() == 0) {
continue;
}
//另外,一般第一列都标识列,如果第一个格没数据,则认为该行数据无效,要跳过
//注意:getStringCellValue()读取的格必须是文本,否则抛异常
if (StringUtils.isNotBlank(row.getCell(0).getStringCellValue())) {
Region region = new Region();
region.setId(row.getCell(0).getStringCellValue());
region.setProvince(row.getCell(1).getStringCellValue());
region.setCity(row.getCell(2).getStringCellValue());
region.setDistrict(row.getCell(3).getStringCellValue());
region.setPostcode(row.getCell(4).getStringCellValue());
regionList.add(region);
}
}
//调用service保存数据
regionService.saveRegionBatch(regionList);
//解析成功
resultMap.put("result", true);
//关流
is.close();
} catch (Exception e) {
e.printStackTrace();
//解析失败
resultMap.put("result", false);
}
//将装有结果集的map压入栈顶
pushToValueStack(resultMap);
//返回json类型
return JSON;
}
}