struts2实现文件上传的方式比较固定,说固定是指必须按照struts2的要求来定义action中的变量,必须的变量是一个类型为File的属性,属性名称需要和前端页面上定义的<input type="file" name="uploadfile"/>属性名一致,如果是多文件上传,这里的File还必须定义为数组类型的。
下面具体介绍文件上传实现方式:
定义action,需要声明三个变量。分别指定上传文件xx,上传文件名xxFileName,上传文件类型xxContentType。文件名随便定义,只要与页面一致即可,而文件名必须是xxFileName,而且"FileName"不能变,同理"ContentType"也不能变。本人亲测,不定义上传文件类型xxContentType,可以上传成功,但是日志中会打印一个Error级别错误。所以为了规范,还是按照规定来声明。
这里的文件上传采用了commons-io提供的FileUtils.copyFile(src,dest)方法,项目中需要引入commons-io,commons-fileupload的依赖库。当然,也可以采用传统的io流的方式将文件写入服务器磁盘。
页面内容如下:
主要代码:
<form action="upload!save.action" method="post" enctype="multipart/form-data">
<label>选择文件</label>
<input type="file" name="uploadfile" id="uploadfile"/>
<input type="submit" value="点击上传"/>
</form>
定义form表单的方法类型post,action对应后台上传方法upload!save.action,关键点在enctype上,需要设置为multipart/form-data。form表单中定义一个文件选择标签:<input type=file name="uploadfile" id="uploadfile"/>。
这样一个上传的demo就做好了。但是这个demo很糙,传统的crm项目中会这么做。在用户体验稍微好点的应用中,这种同步提交表单的方式逐步被淘汰了,取而代之的是异步提交的方式,上传完成了,至少告诉用户一声,或者能够显示上传进度更好(flash插件swfupload上传的方式)。这里使用ajaxfileupload插件,来做一个异步上传文件的demo。
首先我们需要下载jquery库,ajaxfileupload.js库,因为ajaxfileupload是基于jquery开发的。
有的ajaxfileupload版本是基于老版本的jquery开发的,如果报jQuery.handleError is not a function,那么就需要在ajaxfileupload代码中加入如下代码:
handleError方法只在jquery1.4版本中用到。所以使用高版本的jquery,而且上传过程出现异常,就会报这个错。
上传页面核心代码:
<div>
<form action="upload!save.action" method="post" enctype="multipart/form-data">
<label>选择文件</label>
<input type="file" name="uploadfile" id="uploadfile"/>
<input type="submit" onclick="return upload();" value="点击上传"/>
</form>
</div>
</body>
<script type="text/javascript" src="js/libs/jquery-1.12.4.min.js"></script>
<script type="text/javascript" src="js/libs/ajaxfileupload.js"></script>
<script type="text/javascript">
function upload(){
$.ajaxFileUpload({
url:'upload!save.action',
dataType:'json',
fileElementId:'uploadfile',
insecure:false,
success:function(data,status){
if(data.code==200){
alert(data.msg);
}else{
alert(data.error);
}
},
error:function(data,status,e){
alert(e);
}
});
return false;
}
</script>
增加了jquery,ajaxfileupload库,再加一个调用ajaxfileupload api方法。参数中需要注意的是fileElementId,需要传入<input type=file/>标签id。
后台上传方法这时候就不能是普通的method,返回string,需要返回json格式,并且返回数据格式{"code":200,
msg:"success","error":""}。需要与ajaxfileupload方法success,error中参数结构对应。
public String save(){
Map<String, Object> result = new HashMap<String, Object>();
String path = ServletActionContext.getServletContext().getRealPath("/uploads");
File destFile = new File(path,uploadfileFileName);
try {
FileUtils.copyFile(uploadfile, destFile);
log.warn("file->"+uploadfileFileName+" upload successfully.");
result.put("code", 200);
result.put("msg", "success");
result.put("error", "");
} catch (IOException e) {
e.printStackTrace();
result.put("code", 500);
result.put("msg", "fail");
result.put("error", "server error");
}
return ajax(result);
}
public String ajax(Object out){
PrintWriter writer = null;
try {
HttpServletResponse response = ServletActionContext.getResponse();
response.setContentType("application/json;charset=utf-8");
writer = response.getWriter();
response.setDateHeader("Expires", 0);
JSONObject object = JSONObject.fromObject(out);
writer.write(object.toString());
writer.flush();
} catch (Exception e) {
e.printStackTrace();
}finally{
if(writer!=null){
writer.close();
}
}
return null;
}
上传前:
上传成功之后,弹出提示:
相比表单同步提交,这种方式多了一些交互,如果加上一些css样式,可以做出一个很好看的上传。