您的位置:首页 > 其它

使用 Anthem.NET 1.5中的FileUpload控件实现Ajax方式的文件上传

2010-03-03 22:15 781 查看
Anthem.NET(我的介绍和比较,还有一篇)刚刚发布了其最新的1.5版本,其中很不错的一个新功能就是对文件上传功能的Ajax实现。本文将简要介绍一下该功能的使用方法。

Anthem.NET的下载与安装
Anthem.NET可以在此下载:http://sourceforge.net/project/showfiles.php?group_id=151897&package_id=168043&release_id=493609
下载之后解压缩至硬盘中的某一目录中,编译项目得到Anthem.dll。然后将其拷贝到Web站点的bin目录下:
打开Web站点的Web.config文件,在 configuration>/ / / 中添加如下一行,注册Anthem.NET控件:

Anthem.NET提供了一套自己就带有Ajax功能的、继承于现有ASP.NET控件的服务器端控件。根据上面在web.config文件中的注册,这部分控件的前缀为anthem。
Anthem.NET支持ASP.NET 1.1和ASP.NET 2.0,不过本文的示例程序均基于ASP.NET 2.0。

普通的ASP.NET文件上传
先看一下普通的ASP.NET文件上传功能的实现,代码如下:

后台代码,只是简单地将文件名和文件大小显示出来:
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。那个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("");
} 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;
}
0
0
0
(请您对文章做出评价)
« 上一篇:周年纪念
» 下一篇:ASP.NET AJAX (Atlas) 拖放(Drag & Drop)功能6种实现方法总结
本贴子以“现状”提供且没有任何担保,同时也没有授予任何权利
This posting is provided "AS IS" with no warranties, and confers no rights.
posted on 2007-03-25 12:10 Dflying Chen 阅读(8882) 评论(55) 编辑 收藏 所属分类: 新技术介绍, ASP.NET AJAX (Atlas)
评论:
1113986
#1 楼 2007-03-25 12:19 | Neo.h
从1.2的版本的时候就开始用了,反而觉得1.2的版本比较稳定。1.3以上包括使用1.5的当过程较复杂的时候经常使用UpdateAfterCallback=true这句话是都是没有反应更新不了,使用回1.2的控件就可以不知道你碰到这样的情况没有。
回复 引用 查看
#2 楼[楼主] 2007-03-25 12:25 | Dflying Chen
@Neo.h
1.2的时候还没有FileUpload吧?
我也是浅尝辄止随便试试看,呵呵,没什么实际使用经验。不过版本越高,估计功能就越丰富,自然出错的可能性就大了……
回复 引用 查看
#3 楼 2007-03-25 12:34 | Neo.h
@dflying
不好意思,没表达清楚。我说的不只是FileUpload,Anthem.NET里面的所有控件基本上都有 UpdateAfterCallback这个方法,用来通知控件更新显示的方法。1.2里面也有,1.5也有。只不过使用1.2从来没有这样的问题,1.3的版本出来以后就碰到这样的问题,到1.5那天我去下载来试了一下还是有这样的问题。在IE里面设置了允许客户端调试,发现当很多的控件集合在一起使用的时候方法里面所有的过程都执行了一遍,最后执行UpdateAfterCallback=true;还是没有更新控件的显示,换到了1.2的版本显示又正常了。真是挺怪的。所以到了现在还是用回1.2版本的,觉得还是1.2实用。
回复 引用 查看
#4 楼[楼主] 2007-03-25 12:38 | Dflying Chen
@Neo.h
恩,如果自己解决不了的话,给开发者发一个Bug吧,呵呵
功能丰富了,可能一些bug就会出现
回复 引用 查看
#5 楼 2007-03-25 12:47 | Neo.h
@Dflying
谢谢你的建议,以后如果你有研究Anthem.NET这方面话的希望大家能互相交流学习。
回复 引用 查看
#6 楼[楼主] 2007-03-25 12:50 | Dflying Chen
@Neo.h
谢谢你的关注,欢迎常来看看,我们一起探讨!
回复 引用 查看
#7 楼 2007-03-25 13:06 | Jeffrey Zhao
对于实现很感兴趣,能不能介绍一下啊?:)
回复 引用 查看
#8 楼 2007-03-25 14:01 | 木野狐
关注,不过现在暂时不怎么做 .net 了。
回复 引用 查看
#9 楼[楼主] 2007-03-25 14:13 | Dflying Chen
@Jeffrey Zhao
更新在文章中了……本来想贴在回复中,没想到居然是这个错误???
---------------------------
Error
---------------------------
A Runtime Error has occurred.
Do you wish to Debug?
Line: 279
Error: The disk is full.

---------------------------
Yes No
---------------------------
回复 引用 查看
#10 楼[楼主] 2007-03-25 14:13 | Dflying Chen
除了用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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: