先給大家貼代碼了,后面給大家在做具體的文字說明。
以下是前端代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
<%@ 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" />
1
2
3
4
5
6
|
<input type= "button" id= "btnDownLoad" value= "無刷新下載文件" /> <div id= "loadingbox" style= "display:none;" > 正加下載中,請稍候。。。 </div> </body> </html> |
以下是服務器端代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
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] ?? "N" ).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技術來實現。