iframe實現無刷新上傳下載

        最近我維護的網站在審覈時加了個上傳下載的功能,能上傳多個文件(文件很小、不超過3個、上傳時可以多選、且要有上傳進度),下載時有選擇的下載。頁面是用aspx做的,微軟自帶的只有單文件上傳,於是乎想到flash。找了三個現成的,測試發現一個不兼容IE9,另兩個都通過了,但發現有點山寨,flash是封裝好的,一個上面有廣告,一個是英文的,既是封裝的,我也不知道里面到底幹了什麼,也沒想去看As語言的語法。後來又找了個silverlight的,效果不錯,但新的問題又有了,flash到時大多數電腦都裝了的,但silverlight沒裝的人就多了去了,雖然給了下載的鏈接,但還是反映很差,時間又緊,無奈將功能裁減了點,上傳時不顯示實時進度,找了博客園上的cloudgamer寫的仿163網盤的無刷新多文件上傳系統自己稍微改了改就用上去了。下載找的這篇文章,用的是aspx的UpdatePanel。上傳的效果如下:

 

        任務是完成了,但明顯發現整合到我們項目中之後比較搓,我們項目用的Jquery,而這裏是純js(剛開始在IE9下還有Bug),我對js也不太熟悉,感覺這裏還有些問題,於是花了點時間研究了裏面的相關js語法,將基本的原理抽象出來,用Jquery寫了個上傳下載的例子,都是通過iframe實現的。

        先說上傳:上傳本質是通過提交自帶的file控件,然後對a標籤做了點處理,首先a標籤做成圖片的,a標籤裏面是file控件,然後每次選擇文件後將這個file控件隱藏,新建一個file控件,這樣就實現了點擊一個圖標上傳多個文件。下面給出最基本的實現,至於實時顯示選擇的文件、已經上傳的文件以及其他取消的功能就看各人的發揮了。

        下面貼出代碼:Form窗體的代碼

 <form id="uploadForm" action="FileUpLoad.ashx">
    <table>
        <tr>
            <td>
                <a href="javascript:void(0);" class="files" id="idFile"></a>
            </td>
            <td>
                <input id="idBtnupload" type="button" value="開始上傳" />
            </td>
        </tr>
    </table>
</form>

        js的代碼:

$(document).ready(function () {
    //註冊按鈕的點擊事件
    $("#idBtnupload").click(btnUpLoad_onclick);
    CreateFrame();
    Init();
})
///創建iframe
function CreateFrame() {
    var FrameName = "uploadFrame_" + Math.floor(Math.random() * 1000);
    var oframe = $('<iframe name=' + FrameName + '>');
    //修改樣式是css,修改屬性是attr
    oframe.css("display", "none");
    //在內部的前面加節點
    $('body').prepend(oframe);
    //設置form屬性,關鍵是target要指向iframe
    $("#uploadForm").attr("target", FrameName);
    $("#uploadForm").attr("method", "post");
    //注意ie的form沒有enctype屬性,要用encoding
    $("#uploadForm").attr("encoding", "multipart/form-data");
}
///上傳
function btnUpLoad_onclick() {
    $("#uploadForm").submit();
}
///初始化時新建一個file類型文本框
function Init() {
    var fileJquery = $("<input type='file'>").attr("name", "Test").attr("title", "Jquery");
    //這是運用js的onchange屬性賦值的(不知道用Jquery怎麼實現,用Jquery綁定方法沒能實現)
    fileJquery[0].onchange = function () { return OperateAndNew(fileJquery[0]); };
    fileJquery.appendTo("#idFile");
}
///每當添加一個附件時執行
function OperateAndNew(o) {
    if (o.value != "") {
        o.style.display = "none"
        Init();
    }
}
///上傳完成後提示消息
function Finish(msg) {
    alert(msg);
}

        後臺處理程序的代碼:

using System.Web;
using System.IO;

namespace UpLoadAndDown1021.上傳文件
{
    /// <summary>
    /// FileUpLoad 的摘要說明
    /// </summary>
    public class FileUpLoad : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            int iTotal = context.Request.Files.Count;
            for (int i = 0; i < iTotal; i++)
            {
                HttpPostedFile file = context.Request.Files[i];
                if (file.ContentLength > 0 || !string.IsNullOrEmpty(file.FileName))
                {
                    //保存文件
                    file.SaveAs(System.Web.HttpContext.Current.Server.MapPath("./UpLoadFile/" + Path.GetFileName(file.FileName)));
                }
            }
            context.Response.Write("<script>window.parent.Finish('上傳文件成功!');</script>");
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}

        其次是下載:一開始用的a標籤,直接點擊下載,後來發現文本或者圖片的話就不行,會直接在瀏覽器中打開;後來用Ajax異步調用時,但總有問題,我希望直接通知瀏覽器下載,而不是返回前臺;於是也用iframe實現,本質上就是創建了一個iframe,然後將其指向下載的方法。

        前臺Form的代碼:

    <form id="idForm" action="">
    下載文件:<input type="text" id="AnnexName" value="絕密資料共享.txt" />
    <br />
    文件全路徑:<input type="text" style="width: 500px" id="FullName" value="D:\pfeEXE\UpLoadAndDown1021\Demo.DownLoad\TestFile\絕密資料.txt" />
    <br />
    <input type="button" id="btnDownLoad" name="Test" value="DownLoad" />
    </form>

        js代碼:

$(document).ready(function () {
    $("#btnDownLoad").click(btnDownLoad_onclick);
})
function CreateFrame() {
    var AnnexName = $("#AnnexName").val();
    var FullName = $("#FullName").val();
    var FrameName = "uploadFrame_" + Math.floor(Math.random() * 1000);
    var oframe = $('<iframe name=' + FrameName + '>');
    //修改樣式是css,修改屬性是attr
    oframe.css("display", "none");
    oframe.attr("src", "DownLoad.aspx?opType=" + "DownLoadAnnex" + "&AnnexName=" + AnnexName + "&FullName=" + FullName);
    //在內部的前面加節點
    $('body').prepend(oframe);
}
function btnDownLoad_onclick() {
    CreateFrame();
}

        後臺處理程序的代碼:

using System;
using System.IO;
namespace UpLoadAndDown1021.Demo.DownLoad
{
    public partial class DownLoad : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (Request.QueryString["opType"] == "DownLoadAnnex")
            {
                ///完整路徑名(包括文件名)
                string fulleName = Request["FullName"];
                ///下載保存的文件名
                string dispalyName = Request["AnnexName"];
                DownLoadFile(fulleName, dispalyName);
            }
        }
        /// <summary>
        /// 下載文件
        /// </summary>
        /// <param name="FullName">待下載的全路徑</param>
        /// <param name="DisPalyName">顯示的名稱</param>
        private void DownLoadFile(string FullName, string DisPalyName)
        {
            if (File.Exists(FullName))
            {
                FileInfo file = new FileInfo(FullName);
                Response.ContentEncoding = System.Text.Encoding.GetEncoding("UTF-8"); //解決中文亂碼
                Response.AddHeader("Content-Disposition", "attachment; filename=" + Server.UrlEncode(DisPalyName)); //解決中文文件名亂碼    
                Response.AddHeader("Content-length", file.Length.ToString());
                Response.ContentType = "appliction/octet-stream";
                Response.WriteFile(file.FullName);
                Response.End();
            }
            else
            {
                //可以提示文件不存在或已丟失
            }
        }
    }
}

        至此完成,只是思想,實現的業務還很少,其他還有實時文件上傳狀態、進度等。項目源代碼。歡迎閱讀、討論、轉載,轉載請保留原文地址





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章