65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 JavaScript 下载文件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.39/5 (11投票s)

2010年1月29日

CPL

2分钟阅读

viewsIcon

255092

downloadIcon

6346

一篇关于如何使用 JavaScript 下载文件的文章。

FileDownloadUsingJavascript_Src

引言

我知道很多开发者像我一样也在寻找这种解决方案。 我有同样的需求,即使用 JavaScript 从服务器下载文件,而无需回发整个页面。 它的优点在于,它可以在 IE/Firefox/Chrome 浏览器中工作。 我没有使用 ScriptManager/UpdatePanel 任何东西,而是使用了 Handler 和普通的 JavaScript 代码。 Handler 用于将响应写回页面。 我记录了您可能在编程中使用的步骤。 我不能在 Firefox 中使用 ActiveXObject 创建 Excel 对象,因为 ActiveXObject 在 Firefox 中不起作用。

我是如何做到的?

  1. 在页面上添加 span 标签,它将作为链接工作
  2. 创建 FileHandler.ashx 以将响应写回页面。
    public void ProcessRequest(HttpContext context)
        {
            fileName = HttpUtility.UrlDecode(context.Request.Params["fileName"]);
    
            string FullFilePath = context.Server.MapPath("~/Common/Files/" + fileName);
            FileInfo file = new FileInfo(FullFilePath);
            if (file.Exists)
            {
                context.Response.ContentType = 
    		MIMETypeUtility.MIMETypeDescription(MIMEType.Excel);
                context.Response.AddHeader
    	    ("Content-Disposition", "attachment; filename=\"" + file.Name + "\"");
                context.Response.AddHeader("Content-Length", file.Length.ToString());
                context.Response.WriteFile(file.FullName);
                context.Response.End();
            }
        }    

    您可以根据需要使用任何 MIME 类型。 我展示了一些您可以在应用程序中使用的 MIME 类型。 有关更多 MIME 类型,请参阅 http://msdn.microsoft.com/en-us/library/ms775147%28VS.85%29.aspx

    public enum MIMEType
    {
        [DescriptionAttribute("text/HTML")]TextHTML,
        [DescriptionAttribute("image/GIF")]Gif,
        [DescriptionAttribute("image/JPEG")]JPEG,
        [DescriptionAttribute("text/plain")]TextPlain,
        [DescriptionAttribute("Application/msword")]Word,
        [DescriptionAttribute("Application/vnd.ms-excel")]Excel,
        [DescriptionAttribute("Application/vnd.xls")]FirefoxExcel
    }
    public class MIMETypeUtility
    {
        public static string MIMETypeDescription(Enum mimeType)
        {
            FieldInfo fi = mimeType.GetType().GetField(mimeType.ToString());
            DescriptionAttribute[] attributes = 
               	(DescriptionAttribute[])fi.GetCustomAttributes
                	(typeof(DescriptionAttribute), false);
            if (attributes.Length > 0)
            {
                return attributes[0].Description;
            }
            else
            {
                return mimeType.ToString();
            }
        }
    }    
  3. 创建 FileHandler.js 文件来完成主要工作。 它将动态创建一个 iframe,其宽度、高度和边框均为 0。 然后创建一个表单标签,其中包含一个输入控件,用于在提交 iframe 时传递文件名(例如 ExcelFile.xls)。
    var createFrame = function() 
    {
        var frame = document.createElement("iframe");
        frame.name = "fileFrame";
        frame.id = "fileFrame";
    
        document.body.appendChild(frame);
        generateIFrameContent();
        frame.style.width = "0px";
        frame.style.height = "0px";
        frame.style.border = "0px";
    }
  4. GetExcelFile 函数会将 Excel 文件名作为参数传递,并提交一个 iframe 窗口,handler 将运行代码并将文件响应写回页面,用户将获得打开/保存/取消对话框。
    var getExcelFile = function()
    {
        var frmWindow = getIFrameWindow();
        var fileName = frmWindow.document.getElementById("fileName");
        fileName.value = encodeURI("ExcelFile.xls");
        var frm = frmWindow.document.getElementById("frmFile");
        frm.submit();
    }    
  5. 创建 LoadScript.aspx 页面以将脚本添加到页面响应。 您可以在此处添加任意数量的脚本,我更喜欢这种方式,这样可以在运行时隐藏 JavaScript 和脚本文件的位置。
    private void loadScript()
        {
            List<string> scripts = new List<string>();
            scripts.Add(Server.MapPath("~/Common/JS/FileHandler.js"));
    
            try
            {
                bool isStyles = this.GetType().BaseType.Name == "Styles";
                this.Response.Clear();
                this.Response.ContentType = isStyles ? "text/css" : "text/javascript";
                byte[] data = null;
    
                try
                {
                    StringBuilder sb = new StringBuilder();
                    foreach (string str in scripts)
                        sb.Append(File.ReadAllText(str));
                    data = new ASCIIEncoding().GetBytes(sb.ToString());
                }
                catch (Exception ex)
                {
                    throw ex;
                }
    
                this.Response.AddHeader("Content-Length", data.LongLength.ToString());
                this.Response.BinaryWrite(data);
                this.Response.End();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }    
  6. 将以下代码添加到 FileHandler.aspx 页面以加载脚本并使用初始化 JavaScript 函数的启动脚本。
    protected void Page_Load(object sender, EventArgs e)
    {
        Type type = this.GetType();
        if (!this.ClientScript.IsClientScriptIncludeRegistered(type, "scrScripts"))
             this.ClientScript.RegisterClientScriptInclude
    		(type, "scrScripts", "Common/Loaders/LoadScripts.aspx");
        if (!this.ClientScript.IsStartupScriptRegistered(type, "scrHandlerStartUp"))
             this.ClientScript.RegisterStartupScript
    		(type, "scrHandlerStartUp", GetStartUpScript(), true);
    }
    
    private string GetStartUpScript()
    {
        return "try{{var handler = new FileHandler();handler.init();}}catch(e)
    	{{document.getElementById('divNotLoaded').style.display = '';}}";
    }    

结论

您可以使用 AJAX(Scriptmanager + Updatepanel)从服务器下载文件,但您必须回发页面。 这种技术对页面来说是轻量级的。 我的项目需求是从数据库中获取数据,创建一个 Excel 文件,插入数据并将文件下载到用户机器。 并且我的整个网站都在使用 AJAX(JS+WebServices 并且没有 updatepanel),在这种情况下我不能使用任何服务器控件,因为那将会回发我的整个页面,而我不想让这种情况发生。 因此,经过大量的研发和许多方法,这是我使用的一种技术,并且它在生产环境中运行成功。 如果您有任何问题,请通过 phani.nadigadda@gmail.com 与我联系。

历史

  • 2010 年 1 月 29 日:初始版本
© . All rights reserved.