实现一个Ajax模式的文件上传功能有多难?

本文介绍了一种使用iframe实现Ajax模式的文件上传方法。通过将文件输入元素从主表单复制到专门用于上传的隐藏表单中,并利用隐藏的iframe进行提交,实现了文件的异步上传。文章详细解释了实现步骤和技术细节。
如题所示,实现一个Ajax模式的文件上传有多难?这并不是一个疑问句,这是一个反问句。
在这里我先声明,不要认为一提到Ajax就是讲XHttpRequest, Ajax还要包括基于frame的操作,对!我说的是古老的frame。
xhttpRequest并不能实现文件上传,所以涉及到文件的上传,我们还得回到frame上,尤其是iframe。

需要的材料:
1,你掌握基本的Javascript技能。
2,一个隐藏的form和iframe,这里我分别命名为uploadForm和uploadResponse.
3,一个负责接收文件的页面,名字叫做UploadImage.aspx。
4,一个负责显示文件的页面,名字叫做File.aspx。

基本原理:
通过复制当前form(form1)中的input type=file 的html元素到另一个专用于文件上传的form(uploadForm)中,而切uploadForm的target指向到一个隐藏的iframe( uploadResponse)框架的name.这样,当执行uploadForm的submit()操作时,就会通过 uploadResponse将uploadForm的内容post到UploadImage.aspx页面去执行,由于iframe元素uploadResponse及form元素uploadForm元素都是位于一个隐藏的div元素中,所以访问者自始至终都不会见到多余的东西。

实例:
Default.aspx页面。
< script  type ="text/javascript" >

    
function uploadImage() {
        
var file = document.getElementById("imageFile");
        
var uploadFormElement = document.getElementById("uploadForm");

        
//显示进度条
        document.getElementById("processDiv").style.display = "block"// the progress div

        
//复制图片数据
        uploadFormElement.removeChild(uploadFormElement.imageFile);
        uploadFormElement.appendChild(file);
        document.getElementById(
"uploadImageDiv").innerHTML = '<input type="file" id="imageFile" name="imageFile" />';

        
//提交图片数据
        uploadFormElement.submit();
    }


    
function uploadImageResponse(response) {
        document.getElementById(
"processDiv").style.display = "none"// hide progresss div
        var errLabel = document.getElementById("uploadMessage");
        errLabel.innerHTML 
= "";
        window.eval(
"var k=" + response);
        
if (k.status == 1)
            errLabel.innerHTML 
= k.message;
        
else if (k.status == 2)
            errLabel.innerHTML 
= k.message;
        
else
            eval(
"tinyMCE.activeEditor.dom.add(tinyMCE.activeEditor.getBody(), 'img', { src:'" + k.message + "',style:'border:0px;'}, null);");

    }


    
function uploadButton_onclick() {

    }


    
</ script >

    
< form  id ="form1"  runat ="server" >
    
< div >
        
<!--  Gets replaced with TinyMCE, remember HTML in a textarea should be encoded  -->
        
< tinymce:TextArea  ID ="elm1"  theme ="advanced"  plugins ="spellchecker,safari,pagebreak,style,layer,table,save,advhr,advimage,advlink,emotions,iespell,inlinepopups,insertdatetime,preview,media,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,template"
            theme_advanced_buttons1
="bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,fontselect,fontsizeselect,forecolor,backcolor,image"
            theme_advanced_buttons2
=""  theme_advanced_buttons3 =""  theme_advanced_buttons4 =""
            theme_advanced_toolbar_location
="top"  theme_advanced_toolbar_align ="left"  theme_advanced_path_location ="bottom"
            theme_advanced_resizing
="true"  runat ="server"   />
        
< div  style ="margin-top: 5px" >
            上传图片:
            
< br  />
            
< div  id ="uploadImageDiv" >
                
< input  type ="file"  id ="imageFile"  name ="imageFile"   /></ div >
            
< input  type ="button"  id ="uploadButton"  onclick ="uploadImage();"  value ="上传"   />
            
< span  id ="uploadMessage"  style ="border: 1px solid #cccccc; color: Red;" ></ span >
        
</ div >
        
< div  id ="processDiv"  style ="display: none; color: #660066; font-family: Arial;" >
            
< img  src ="/images/loading2.gif"  alt ="uploading"   />
            图片上传中 
< span  id ="fileName"   />
        
</ div >
    
</ div >
    
</ form >
    
< div  style ="display: none;" >
        
< iframe  name ="uploadResponse" ></ iframe >
        
< form  id ="uploadForm"  action ="UploadImage.aspx?t=<%= DateTime.Now.Ticks %>"  target ="uploadResponse"
        method
="post"  enctype ="multipart/form-data" >
        
< input  type ="file"  name ="imageFile"  value =""   />
        
</ form >
    
</ div >

如上所示,首先选择准备上传的文件,然后当你点击上传按钮(name为uploadButton)时,调用uploadImage函数,该函数的作用是复制form1的input type=file的imageFile元素到uploadForm中,并替换原始的imageFile的outerhtml(原因是javascript不支持修改input type=file的元素的value属性),当然还有显示可爱的上传进度条(这样显得我们既专业又酷)。

 function uploadImage()  {
        var file 
= document.getElementById("imageFile");
        var uploadFormElement 
= document.getElementById("uploadForm");

        
//显示进度条
        document.getElementById("processDiv").style.display = "block"// the progress div

        
//复制图片数据
        uploadFormElement.removeChild(uploadFormElement.imageFile);
        uploadFormElement.appendChild(file);
        document.getElementById(
"uploadImageDiv").innerHTML = '<input type="file" id="imageFile" name="imageFile" />';

        
//提交图片数据
        uploadFormElement.submit();
    }

当用户点击上传按钮时,工作转由UploadImage.aspx程序接手。
   protected   void  Page_Load( object  sender, EventArgs e)
        
{
            Page.Response.Cache.SetCacheability(HttpCacheability.NoCache);



            
int status = 0;//状态
            string message = "";//反馈信息

            
//检查文件
            if (Request.Files.Count == 0)
            
{
                status 
= 1;
                message 
= "请先选择要上传的文件";
                RenderUploadScript(status, message);
            }

            
string ext = Path.GetExtension(Request.Files[0].FileName).ToLower();
            
if (ext != ".jpg" && ext != ".jpeg")
            
{
                status 
= 2;
                message 
= "抱歉,目前仅支持jpg格式的图片";
                RenderUploadScript(status, message);
            }


     
                Guid fileID 
= Guid.NewGuid();
                
string fileName = Server.MapPath(String.Format("~\\Files\\{0}.jpg",fileID));
                Request.Files[
0].SaveAs(fileName);
                 
//记录到当前页面

            RenderUploadScript(
0,String.Format( "File.aspx?key={0}",fileID));
        }


        
private   void  RenderUploadScript( int  status,  string  mess)
        
{
            
string script = string.Format("<script language='javascript'> window.parent.uploadImageResponse(\"{{ status:{0},message:'{1}'}}\"); </script>", status, mess);
            Response.Write(script);
            Response.End();
        }


通过HttpWebRequest对象,我们能够获得任何由客户端post或get到服务器端的数据,UploadImage.aspx页面的工作很简单,只负责接收post过来的文件,并保存到指定的位置(方便演示,我仅仅使用了SaveAs)。
另外,要注意到一点,由于是Ajax模式的文件上传,意味着你的程序要通过javascript反馈系统出现的问题,这里我通过一个名称为status的参数来返回出现的问题,0则为一切正常,1则为用户没有提供文件,2则为用户没有上传我指定的文件类型。
当用户上传的文件没有任何问题的时候,系统保存文件并返回状态0,并附加文件的显示路径,其他状态附属的信息则是错误信息。
现在回到Default.aspx来看如何接收UploadImage.aspx反馈回来的信息,这里要考虑到UploadImage.aspx是个页面,而且隶属与iframe元素uploadResponse,所以我们通过javascipt来访问uploadResponse的所属window的对象或函数的写法如下:
"<script language='javascript'> window.parent.uploadImageResponse(\"{{ status:0,message:'File.aspx?key=guid'}}\");<script>"
Default的接应脚本则如下:
   function  uploadImageResponse(response)  {
        document.getElementById(
"processDiv").style.display = "none"// hide progresss div
        var errLabel = document.getElementById("uploadMessage");
        errLabel.innerHTML 
= "";
        window.eval(
"var k=" + response);
        
if (k.status == 1)
            errLabel.innerHTML 
= k.message;
        
else if (k.status == 2)
            errLabel.innerHTML 
= k.message;
        
else
            eval(
"tinyMCE.activeEditor.dom.add(tinyMCE.activeEditor.getBody(), 'img', { src:'" + k.message + "',style:'border:0px;'}, null);");

    }


仅仅是在对应的htm编辑器的内容中插入message附带的信息。

ok!!主要的难点我们都解决了。下面则是要让我们能够看到我们传上去的文件,如果不能实时看到,这个Ajax 文件上传就没啥意义了。
File.aspx页面的功能代码如下:
  protected   void  Page_Load( object  sender, EventArgs e)
        
{

            Guid key 
= new Guid(Request.QueryString["key"]);

            
//图片所在路径
            string fileName = Server.MapPath(String.Format("~/Files/{0}.jpg", key));
            
// Send the file
            Response.ContentType = "image/jpeg";
            Response.WriteFile(fileName, 
true);
            Response.AddFileDependency(fileName);
            Response.Cache.SetCacheability(HttpCacheability.Public);
            Response.Cache.SetAllowResponseInBrowserHistory(
true);
        }
OK!一切都完成了。
演示程序下载地址:
http://files.cnblogs.com/csharpsharper/CoolThingsShow.rar


博主推荐:

Ajax正在将我们带入到下一代的网络应用中。本书深入探讨了动态的网络应用,将Ajax和REST集成在一起作为单独的解决方案。一个很大的优势是,与Ajax相似,REST可以和现今存在的技术一起使用。现在上百万的客户端计算机都是基于Ajax的,上百万的服务器是基于REST的。. 无论你是否开发过Ajax应用程序,这都是一本理想的书。因为这本书描述了各种各样的模式和最好的实践经验。通过此书的学习,你可以快速地检查和校验你是否构造了一个高效的Ajax应用程序。...

购买Logo

转载于:https://www.cnblogs.com/csharpsharper/archive/2008/08/07/uploadfilewithiframe.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值