先给大家贴代码了,后面给大家在做具体的文字说明。
以下是前端代码:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm2.aspx.cs" Inherits="WebApplication1.WebForm2" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> <script src="Scripts/jquery-1.8.2.js"></script> <script type="text/javascript"> $(function () { $("#btnDownLoad").on("click", function () { var $loading = $("#loadingbox"); var downId = new Date().getTime() + "-" + Math.random(); $loading.css("display", "block"); DownLoad($("#downfile").val(), downId); var tid=setInterval(function () { $.post("WebForm2.aspx", { getresult: "Y", downid: downId }, function (result) { //document.writeln("result:" + result); if(result=="Y") { clearInterval(tid); $loading.css("display", "none"); alert("下载完成!"); } }); }, 3000); }); function DownLoad(filename,downid) { var $form = $("<form target='' method='post' action='WebForm2.aspx'></form>"); $form.append("<input type='hidden' name='filename' value='" + filename + "'>"); $form.append("<input type='hidden' name='downid' value='" + downid + "'>"); $('body').append($form); $form.submit(); } }); </script> </head> <body>
要下载的文件名:<input type="text" id="downfile" />
<input type="button" id="btnDownLoad" value="无刷新下载文件" /> <div id="loadingbox"> 正加下载中,请稍候。。。 </div> </body> </html>
以下是服务器端代码:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.IO; namespace WebApplication1 { public partial class WebForm2 : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (Request.HttpMethod == "POST") { string getresult = Request.Form["getresult"]; string downId=Request.Form["downid"]; string cacheKey =string.Format("downloadcompleted-{0}-{1}",downId,Request.UserHostAddress); if (getresult == "Y") //判断是否为获取下载结果的请求 { string result = (Cache[cacheKey] ").ToString(); Response.Clear(); Response.Write(result); if(result=="Y") //如果查询到下载完成,则应清除标记下载完成的CACHE { Cache.Remove(cacheKey); } Response.End(); return; } string fileName = Request.Form["filename"]; string localFilePath = Server.MapPath("~/" + fileName); System.IO.FileInfo file = new System.IO.FileInfo(localFilePath); Response.Clear(); Response.ClearHeaders(); Response.Buffer = false; Response.AddHeader("Content-Disposition", "attachment;filename=" + file.Name); Response.AddHeader("Content-Length", file.Length.ToString()); Response.ContentType = "application/octet-stream"; Response.WriteFile(file.FullName); Response.Flush(); Cache.Insert(cacheKey, "Y");//输出所有文件数据后,添加CACHE,并设置downloadcompleted=Y,供页面查询结果使用 Response.End(); } } } }
实现原理:前端通过动态创建FORM用来请求下载的资源,请求参数中必需包含一个downId(我这里还包含了一个要下载的文件名),这个是与服务器端的cache Key相对应的,服务器端接收到下载请求后,会获取下载的文件名及downId,然后依据downId生成一个相对应的cache Key用于标识下载结果,再依据下载文件名获取服务器的文件资源并响应输出文件流供客户端下载,输出完毕后,生成一个Cache,并标记为Y,表明已输出完毕。客户端在下载文件的同时,会每隔3秒请求服务器获取下载完成的Cache标识,若获取到其值为Y,则表明下载完成,服务器立即清除该Cache,客户端作出相应的响应(比如:关闭提示下载的对话框及弹出下载完成的对话框)
效果如下:
经过多个不同的浏览器及大文件压力测试,兼容性良好,都能正常下载并能收到下载完成提示,基于以上原理,可以实现进度条显示,实现原理简述:客户端请求服务器下载资源-->服务器响应并按字节分段依次输出,每次输出时生成CACHE,并保存输出进度,直至全部输出完毕,客户端在请求服务器下载资源的同时,也需要同时每隔几秒请求查询服务器下载进度,直至下载进度为100%停止请求。也可利用HTML5新特性WEBSOCKET技术来实现。