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)**************/"); }
}</pre>
在按照官網的說明進行簡單配置后,從瀏覽器觸發上傳文件操作,在服務器端的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></pre>
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(); }</pre> <p></p>
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