Anthem.NET剛剛發佈了其最新的1.5版本,其中很不錯的一個新功能就是對文件上傳功能的Ajax實現。本文將簡要介紹一下該功能的使用方法。php
Anthem.NET的下載與安裝html
Anthem.NET能夠在此下載:http://sourceforge.net/project/showfiles.php?group_id=151897&package_id=168043&release_id=493609node
下載以後解壓縮至硬盤中的某一目錄中,編譯項目獲得Anthem.dll。而後將其拷貝到Web站點的bin目錄下:web
打開Web站點的Web.config文件,在configuration>\ <system.web>\ <pages>\ <controls>中添加以下一行,註冊Anthem.NET控件:服務器
<add tagPrefix="anthem" namespace="Anthem" assembly="Anthem"/>
Anthem.NET提供了一套本身就帶有Ajax功能的、繼承於現有ASP.NET控件的服務器端控件。根據上面在web.config文件中的註冊,這部分控件的前綴爲anthem。app
Anthem.NET支持ASP.NET 1.1和ASP.NET 2.0,不過本文的示例程序均基於ASP.NET 2.0。dom
普通的ASP.NET文件上傳異步
先看一下普通的ASP.NET文件上傳功能的實現,代碼以下:ide
<asp:FileUpload ID="defaultFileUpload" runat="server" />
<asp:Button ID="defaultUploadButton" runat="server"
OnClick="defaultUploadButton_Click" Text="Upload" />
<asp:Label ID="defaultResultLabel" runat="server" Text=""></asp:Label>
後臺代碼,只是簡單地將文件名和文件大小顯示出來:post
protected void defaultUploadButton_Click(object sender, EventArgs e)
{
defaultResultLabel.Text = string.Format("File \"{0}\" uploaded ({1} bytes).",
defaultFileUpload.FileName,
defaultFileUpload.FileBytes.Length
);
}
Anthem.NET的Ajax文件上傳
Anthem.NET中的Ajax文件上傳功能靠的是其本身的FileUpload控件,其實使用起來和普通的ASP.NET FileUpload控件差很少,下面是HTML部分的代碼:
<anthem:FileUpload ID="anthemFileUpload" runat="server" />
<anthem:Button ID="anthemUploadButton" TextDuringCallBack="uploading..." EnabledDuringCallBack="false"
runat="server" Text="Upload" OnClick="anthemUploadButton_Click" />
<anthem:Label ID="anthemResultLabel" runat="server" Text=""></anthem:Label>
注意控件的前綴都是anthem。那個Button的TextDuringCallBack屬性設置了異步回送時按鈕中的文本;EnabledDuringCallBack屬性讓該按鈕在進行異步回送時禁用,省得用戶等得不耐煩。
後臺代碼一樣是將文件名和文件大小顯示出來,不過注意這一句anthemResultLabel.UpdateAfterCallBack = true;,用來在回調以後更新anthemResultLabel上的文字:
protected void anthemUploadButton_Click(object sender, EventArgs e)
{
anthemResultLabel.Text = string.Format("File \"{0}\" uploaded ({1} bytes).",
anthemFileUpload.FileName,
anthemFileUpload.FileBytes.Length
);
anthemResultLabel.UpdateAfterCallBack = true;
}
示例程序演示
示例程序的界面以下,上面部分是普通的ASP.NET文件上傳,下面是Anthem.NET的Ajax文件上傳:
使用普通的ASP.NET文件上傳,能夠看到頁面有一次閃爍,不過上傳功能沒什麼問題:
而使用下面部分的Anthem.NET的Ajax文件上傳,能夠看到上傳時的界面(按鈕禁用,文本變化):
上傳完成以後,沒有頁面閃爍:
打開Fiddler看看HTTP請求,上面的是傳統上傳,下面是Ajax的,差異顯而易見……
代碼下載
本文提到的完整的示例程序代碼:http://files.cnblogs.com/dflying/AnthemNETFileUploadDemo.zip
更多參考資料
Anthem.NET官方網站:http://sourceforge.net/projects/anthem-dot-net/
Anthem.NET在線文檔:http://anthem-dot-net.sourceforge.net/docs/
Anthem.NET在線示例程序:http://anthem.talloaksoftware.com/Default.aspx
Fiddler官方網站:http://www.fiddlertool.com/
to jeff(實現方式)
除了用IFrame,還有什麼好辦法麼?它也是用的IFrame,相關代碼以下:注意58-61,109-113,131-148這幾段(粗體部分)。
有空的時候改到Atlas裏面吧,呵呵,造福羣衆阿
function Anthem_CallBack(url, target, id, method, args, clientCallBack, clientCallBackArg, includeControlValuesWithCallBack, updatePageAfterCallBack) {
if (typeof(window.Anthem_PreCallBack) == "function") {
var preCallBackResult = Anthem_PreCallBack();
if (!(typeof preCallBackResult == "undefined" || preCallBackResult)) {
if (typeof(window.Anthem_CallBackCancelled) == "function") {
Anthem_CallBackCancelled();
}
return null;
}
}
var encodedData = "";
if (target == "Page") {
encodedData += "&Anthem_PageMethod=" + method;
} else if (target == "MasterPage") {
encodedData += "&Anthem_MasterPageMethod=" + method;
} else if (target == "Control") {
encodedData += "&Anthem_ControlID=" + id.split(":").join("_");
encodedData += "&Anthem_ControlMethod=" + method;
}
if (args) {
for (var argsIndex = 0; argsIndex < args.length; ++argsIndex) {
if (args[argsIndex] instanceof Array) {
for (var i = 0; i < args[argsIndex].length; ++i) {
encodedData += "&Anthem_CallBackArgument" + argsIndex + "=" + Anthem_Encode(args[argsIndex][i]);
}
} else {
encodedData += "&Anthem_CallBackArgument" + argsIndex + "=" + Anthem_Encode(args[argsIndex]);
}
}
}
if (updatePageAfterCallBack) {
encodedData += "&Anthem_UpdatePage=true";
}
// Anthem will normally use an XmlHttpRequest to communicate with the server.
// But if an Anthem.FileUpload control is discovered on the page, then Anthem
// will use a hidden IFRAME instead. This hidden IFRAME is often called an IOFrame
// by AJAX library authors, so that is the name we use here.
var useIOFrame = false;
// Scan the controls on the form and extract their values.
if (includeControlValuesWithCallBack) {
var form = Anthem_GetForm();
if (form != null) {
for (var elementIndex = 0; elementIndex < form.length; ++elementIndex) {
var element = form.elements[elementIndex];
if (element.name) {
var elementValue = null;
if (element.nodeName.toUpperCase() == "INPUT") {
var inputType = element.getAttribute("type").toUpperCase();
if (inputType == "TEXT" || inputType == "PASSWORD" || inputType == "HIDDEN") {
elementValue = element.value;
} else if (inputType == "CHECKBOX" || inputType == "RADIO") {
if (element.checked) {
elementValue = element.value;
}
} else if (inputType == "FILE") {
// If the FILE element has a value (the path to the file), then an
// IOFrame will be used to handle the callback.
useIOFrame = useIOFrame | !(element.value == null || element.value.length == 0);
}
} else if (element.nodeName.toUpperCase() == "SELECT") {
if (element.multiple) {
elementValue = [];
for (var i = 0; i < element.length; ++i) {
if (element.options[i].selected) {
elementValue.push(element.options[i].value);
}
}
} else if (element.length == 0) {
elementValue = null;
} else {
elementValue = element.value;
}
} else if (element.nodeName.toUpperCase() == "TEXTAREA") {
elementValue = element.value;
}
if (elementValue instanceof Array) {
for (var i = 0; i < elementValue.length; ++i) {
encodedData += "&" + element.name + "=" + Anthem_Encode(elementValue[i]);
}
} else if (elementValue != null) {
encodedData += "&" + element.name + "=" + Anthem_Encode(elementValue);
}
}
}
// ASP.NET 1.1 won't fire any events if neither of the following
// two parameters are not in the request so make sure they're
// always in the request.
if (typeof form.__VIEWSTATE == "undefined") {
encodedData += "&__VIEWSTATE=";
}
if (typeof form.__EVENTTARGET == "undefined") {
encodedData += "&__EVENTTARGET=";
}
}
}
if (encodedData.length > 0) {
encodedData = encodedData.substring(1);
}
if (typeof(Anthem_DebugRequestText) == "function") {
Anthem_DebugRequestText(encodedData.split("&").join("\n&"));
}
// Send the callback request to the server. Use an IOFrame if there is a file upload,
// otherwise use an XmlHttpRequest.
if (useIOFrame) {
// To allow multiple requests at the same time, all of the Anthem parameters are
// passed to the server via the querystring
var action = Anthem_GetCallBackUrl();
action = action + "&Anthem_IOFrame=true";
if (updatePageAfterCallBack) {
action = action + "&Anthem_UpdatePage=true";
}
// We could generate an anonymous function on the fly to handle the clientCallBack
// and assign that to the iframe onload event (in fact this is how XmlHttpRequests are
// handled). But that makes it very hard to debug the callback response. Instead
// we will stuff the clientCallBack function and args into an array and then hard code
// the onload event handler. The handler will find the appropriate callback info in
// the array and handle the clientCallBack.
var id = "f" + new String(Math.floor(9999 * Math.random())); // Generate frame number
if (typeof(clientCallBack) == "function") {
var frame = { "id":id, "clientCallBack":clientCallBack, "clientCallBackArg":clientCallBackArg };
callbackFrames.push(frame);
}
// Create a new, invisible iframe to handle the io.
var ioframe = null;
if (window.ActiveXObject) {
ioframe = document.createElement("<iframe name=\"" + id + "\" id=\"" + id + "\" onload=\"Anthem_HandleIOFrameResponse('" + id + "');\"/>");
} else {
ioframe = document.createElement("iframe");
ioframe.id = id;
ioframe.name = id;
ioframe.onload = function (){ Anthem_HandleIOFrameResponse(id); }
}
ioframe.style.visibility = "hidden";
ioframe.style.height = "1px";
document.body.appendChild(ioframe);
// Submit this form in the hidden iframe
var theForm = Anthem_GetForm();
var tempActionUri = theForm.action;
theForm.action = action;
theForm.target = id;
try {
theForm.submit();
} catch (e) {
result = { "value": null, "error": e.message };
if (typeof(Anthem_DebugError) == "function") {
Anthem_DebugError(e.name + ": " + e.message + " (" + e.number + ")");
}
if (typeof(window.Anthem_Error) == "function") {
Anthem_Error(result);
}
}
// Restore the form
theForm.target = "";
theForm.action = tempActionUri;
} else {
var x = Anthem_GetXMLHttpRequest();
var result = null;
if (!x) {
result = { "value": null, "error": "NOXMLHTTP" };
if (typeof(Anthem_DebugError) == "function") {
Anthem_DebugError(result.error);
}
if (typeof(window.Anthem_Error) == "function") {
Anthem_Error(result);
}
if (typeof(clientCallBack) == "function") {
clientCallBack(result, clientCallBackArg);
}
return result;
}
var action = Anthem_GetCallBackUrl();
x.open("POST", url ? url : action, clientCallBack ? true : false);
x.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
x.setRequestHeader("Accept-Encoding", "gzip, deflate");
if (typeof(clientCallBack) == "function") {
x.onreadystatechange = function() {
if (x.readyState != 4) {
return;
}
if (typeof(Anthem_DebugResponseText) == "function") {
Anthem_DebugResponseText(x.responseText);
}
result = Anthem_GetResult(x);
if (result.error) {
if (typeof(Anthem_DebugError) == "function") {
Anthem_DebugError(result.error);
}
if (typeof(window.Anthem_Error) == "function") {
Anthem_Error(result);
}
}
if (updatePageAfterCallBack) {
Anthem_UpdatePage(result);
}
Anthem_EvalClientSideScript(result);
clientCallBack(result, clientCallBackArg);
x = null;
if (typeof(window.Anthem_PostCallBack) == "function") {
Anthem_PostCallBack();
}
}
}
x.send(encodedData);
if (typeof(clientCallBack) != "function") {
if (typeof(Anthem_DebugResponseText) == "function") {
Anthem_DebugResponseText(x.responseText);
}
result = Anthem_GetResult(x);
if (result.error) {
if (typeof(Anthem_DebugError) == "function") {
Anthem_DebugError(result.error);
}
if (typeof(window.Anthem_Error) == "function") {
Anthem_Error(result);
}
}
if (updatePageAfterCallBack) {
Anthem_UpdatePage(result);
}
Anthem_EvalClientSideScript(result);
if (typeof(window.Anthem_PostCallBack) == "function") {
Anthem_PostCallBack();
}
}
}
return result;
}
出處:http://www.cnblogs.com/dflying/archive/2007/03/25/687082.html