zoukankan      html  css  js  c++  java
  • 实现一个Ajax模式的文件上传功能有多难?

    如题所示,实现一个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!一切都完成了。
    演示程序下载地址:
    https://files.cnblogs.com/csharpsharper/CoolThingsShow.rar


    博主推荐:

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

    购买Logo
  • 相关阅读:
    python之路-随笔 python处理excel文件
    eclipse添加注释
    junit单元测试
    【FLEX教程】#008 开发中的问题笔记(慢更…)
    【FLEX教程】#007 如何让JS调用SWF里的方法
    【总结】2014年度总结
    【转】#100 代码运行框
    【实战项目】【FLEX】#900 实现拖控件功能
    【教程】【FLEX】#006 控件位置的拖动
    【教程】【FLEX】#005 拖动
  • 原文地址:https://www.cnblogs.com/csharpsharper/p/uploadfilewithiframe.html
Copyright © 2011-2022 走看看