Uploadify + Struts2 应用之分析与详解
Uploadify是一个Jquery框架下处理批量文件上传的插件,支持多种服务器端软件。遗憾的是,官网(www.uploadify.com)的说明文档做得很不完善,着重于说明Js部分的配置,而没有对服务端的数据接口进行详细说明。而且由于与服务器端进行数据交互的部分被封装在swf文件中,也很难从源代码进行分析。
1) 分析
基于此,为了探索Uploadify在Struts2下的应用接口数据,编写了个小工具程序RequestObserver如下:
package utils; import java.util.Enumeration; import java.util.Iterator; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import com.opensymphony.xwork2.ognl.OgnlValueStack; public class RequestObserver { private HttpServletRequest request; public RequestObserver(HttpServletRequest request) { this.request = request; } public void observe() { String name,pvalue; Object avalue; Enumeration enum1; System.out.println("/***************** Request Observer (Author: Alex Nie)**************/"); // observe Request Header enum1 = request.getHeaderNames(); System.out.println("Request Header:"); while (enum1.hasMoreElements()) { name = (String)enum1.nextElement(); pvalue = request.getHeader(name); System.out.println(" " + name + " ---- " + pvalue); } enum1 = request.getParameterNames(); // observe Request Parameters System.out.println("Request Parameters:"); while (enum1.hasMoreElements()) { name = (String)enum1.nextElement(); pvalue = request.getParameter(name); System.out.println(" " + name + " ---- " + pvalue); } enum1 = request.getAttributeNames(); // observe Request Attributes System.out.println("Request Attributes:"); while (enum1.hasMoreElements()) { name = (String)enum1.nextElement(); avalue = request.getAttribute(name); System.out.println(" " + name + " ---- " + avalue); // observe OgnlValueStack bind by Struts 2 if (avalue instanceof OgnlValueStack) { avalue = (OgnlValueStack)avalue; Map<String,Object> m = ((OgnlValueStack) avalue).getContext(); System.out.println(" >> OgnlValueStack:"); Iterator it = m.keySet().iterator(); Object key; while (it.hasNext()) { key = it.next(); System.out.println (" " + key + " ---- " + m.get(key)); } } } // observe Request Session HttpSession session = request.getSession(false); System.out.println("session: " + session); if (session!=null) { System.out.println(" sessionId: " + session.getId()); enum1 = session.getAttributeNames(); System.out.println("Session Attributes:"); while (enum1.hasMoreElements()) { name = (String)enum1.nextElement(); avalue = session.getAttribute(name); System.out.println(" " + name + " ---- " + avalue); } } System.out.println("/***************** End of Request Observer (Author: Alex Nie)**************/"); } }
在按照官网的说明进行简单配置后,从浏览器触发上传文件操作,在服务器端的Action中接收到相应的Request后,利用上述工具程序输出分析Request中的数据,发现如下:
分析结果
在进行批量文件上传时,Uploadify为每一个上传文件发起一次服务器连接。
在每一次连接中,Uploadify向服务器端传递了7个参数,其中通过request parameters传递了4个String类型参数
Filename: 待上传的文件原名, 内容与后述的xxxxFileName相同
fileext: 允许上传的文件类型,由客户段Js代码中指定的fileExt参数指定
folder: 上传文件在服务期上的保存路径,由客户段Js代码中指定的folder参数指定
Upload: 暂无用处
通过request attributes 传递了3个参数
xxxx : 文件类型,上传的文件内容,xxxx由客户段Js代码中指定的fileDataName参数指定
xxxxFileName: 字符串类型,上传的文件的原名,xxxx由客户段Js代码中指定的fileDataName参数指定,内容与前述的Filename相同
uploadifyContentType: 暂无用处
以上7个参数在服务器端都被Struts2封装,在Action都可直接使用。要注意的是参数名称的大小写和Js端的大小写并不完全相同,有的在 Js中小写服务器端大写,有的刚好相反。此外有两个参数内容相同,这些大约是Uploadify未来在代码风格与约定方面可以改进的地方。
清楚了数据接口,Struts2下对应Uploadify的Action该怎么写就很清楚了,接下来以批量上传照片为例进行说明。
2) 应用详解
html
<input id="file_upload" name="photo" type="file"/> <div id="fileQueue"></div>
Javascript
引入jquery-1.4.2.min.js, swfobject.js, jquery.uploadify.v2.1.4.min.js
引入自己的上传用Js代码如下(精简说明版):
$(document).ready(function() { $('#file_upload').uploadify({ // 页面相关 'uploader' : '/js/uploadify/uploadify.swf', //组件自带的flash,路径根据情况自行调整 'cancelImg' : '/js/uploadify/cancel.png',//取消上传文件的按钮图片 'queueID' : 'fileQueue', //放置上传文件及上传进度的Html元素Id 'queueSizeLimit' : 10, //一次最多选择多少个文件上传 // 控制开关 'auto' : false, //是否选取文件后自动上传,建议关闭 'multi' : true, //多文件上传必须打开 // 服务器脚本 'script' : 'uploadify.action', //Struts2下处理上传的action路径 'scriptData' : {'userid': '12345', 'username': 'Alex Nie'}, //自身业务需要向服务器端传递的数据 // 传递给服务器参数 'folder' : '/upload', //上传文件的目录,将作为'folder'参数传递给服务器 'fileDataName' : 'photo', //它决定了最重要的两个上传参数名称,本例中将为文件'photo'和文件名'photoFileName' 'fileExt' : '*.gid;*.jpg;*.jpeg', //允许的文件类型,在客户端约束用户的文件选择,并将作为'fileext'参数传递给服务器供校验用 // 其它 'fileDesc' : '*.gif;*.jpg;*.jpeg', //显示在本地选择文件对话框的文件类型下拉框中 'sizeLimit' : 100*1024 // 单个文件的最大尺寸(字节为单位) }); }); function uploadFile(){//上传文件 jQuery('#file_upload').uploadifyUpload(); }
Java
在此不列出具体代码了,只说明一下服务器端UploadifyAction程序的大致流程:
定义以下变量,且生成它们的get和set方法
private File photo;
private String photoFileName,fileext,folder;
1) 分析'fileext',分解出允许的所有文件类型;
2) 校验photoFileName是否在允许的文件类型中
3) 校验文件photo的大小是否超标(遗憾的是,Uploadify不会把Js中定义的'sizeLimit'传递给服务器,服务器端必须自行定义)
4) 校验folder指定的路径是否合法
5) 在folder指定的路径下保存文件photo,根据业务需要可能要为它取名而不是用原文件名photoFileName
6) 向response写入成功或失败返回信息,供页面使用
注:如果信任浏览器端的文件类型和文件尺寸约束校验,也可以省略第2、第3步和第4步,不过为了防止恶意的客户端伪装,最好不要省略它们。
其它几个值得使用的Uploadify选项
'removeCompleted': false //完成上传后是否自动清除网页上的文件列表
'displayData' : 'percentage',//有speed和percentage两种选择,一个显示速度,一个显示完成百分比
'buttonImg' : '/images/mybutton.jpg', 可用图片替换掉页面上传按钮的英文文字显示,避开直接替换成中文文字会遇到的编码问题。
解决Uploadify缺省的英文提示窗问题
编辑jquery.uploadify.v2.1.4.min.js,查找'alert'和'confirm'调用,把提示信息从英文改成中文。
转自:http://blog.csdn.net/alexandertech/article/details/6428366