前言
踩過的坑
1、WebAPI跨域
2、Jquery ajax低版本不支持XHR 2功能
3、Jquery ajax不支持Deferred的process事件
4、IE下文件名亂碼問題
功能實現
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title> <meta charset="utf-8" /> <script src="https://code.jquery.com/jquery-3.2.1.min.js "></script> </head> <body> <input type="button" value="全部下載" onclick="doAllDownload()" /> <div> <ul> <li> <span>文件1.txt</span> <span id="progress1"></span> </li> <li> <span>文件2.txt</span> <span id="progress2"></span> </li> <li> <span>文件3.txt</span> <span id="progress3"></span> </li> </ul> </div> <script> function doAllDownload() { /** 測試: 1、文件3數據量大 2、文件2不存在 **/ var files = []; files.push({ url: 'D:\\Test\\1.txt', id: 'progress1' }); files.push({ url: 'D:\\Test\\2.txt', id: 'progress2' }); files.push({ url: 'D:\\Test\\3.txt', id: 'progress3' }); files.forEach(function (item) { //多文件下載 DownloadFile(item.url).then(function (result) { //請求完成 var msg = "文件下載完畢!"; if (result.error) { msg = result.error.message ? result.error.message : "文件下載錯誤!"; } $("#" + item.id).html(msg); }, function (err) { }, function (evt) { //根據item處理進度條數據 $("#" + item.id).html("已下載 " + parseInt(100 * evt.loaded / evt.total) + "%"); }); }) } function DownloadFile(url) { var filename = url.substr(url.lastIndexOf('\\') + 1);//文件名 var dfd = new $.Deferred(); var promise = $.ajax("http://localhost:2032/api/Test/DownloadFileUrl", { type: "POST", contentType: 'application/json', data: JSON.stringify({ url: url }), /*JQuery 3.0以下版本不支持*/ xhrFields: { responseType: 'arraybuffer', onprogress: dfd.notify//觸發dfd.process事件 } }); promise.then(function (data, status, xhr) { if (xhr.statusText == "OK") { var type = xhr.getResponseHeader('Content-Type'); var blob = new Blob([data], { type: type }); if (typeof window.navigator.msSaveBlob !== 'undefined') { window.navigator.msSaveBlob(blob, filename); } else { var URL = window.URL || window.webkitURL; var downloadUrl = URL.createObjectURL(blob); if (filename) { var a = document.createElement("a"); if (typeof a.download === 'undefined') { window.location = downloadUrl; } else { a.href = downloadUrl; a.download = filename; document.body.appendChild(a); a.click(); } } else { window.location = downloadUrl; } setTimeout(function () { URL.revokeObjectURL(downloadUrl); dfd.resolve({}); }, 100); } } else { dfd.resolve({ error: { message: xhr.statusText } }); } }, function (err) { //異常處理 }, function (info) { //不支持Deferred的process事件 }); return dfd; } </script> </body> </html>
Asp.NET后台代碼
1、為了設置進度條 故設置 BUFFER_SIZE 為 5 開發時請注意,跨域設置請自行在Web.config或者WebApiConfig.cs里面設置。就不上代碼了,網上很多例子!
2、文件名亂碼問題:請參考 https://my.oschina.net/pingpangkuangmo/blog/376332
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Web; using System.Web.Http; namespace WebAPI.Controllers { public class TestController:ApiController { private const int BUFFER_SIZE = 5; [HttpPost] public void DownloadFileUrl(dynamic args) { string url = args.url; string filename = url.Substring(url.LastIndexOf('\\') + 1); var response = HttpContext.Current.Response; if (File.Exists(url)) { byte[] buffer = new byte[BUFFER_SIZE]; response.Clear(); //跨域處理 response.AddHeader("Access-Control-Allow-Origin", "*");//支持所有跨域請求 response.AddHeader("Access-Control-Allow-Headers", "*");//支持所有Access-Control-Request-Headers字段 response.ContentType = "application/octet-stream";//定義stream為下載類型的窗口 response.AddHeader("Content-Disposition", "attachment;filename=" + filename); using (var stream = File.Open(url, FileMode.Open, FileAccess.Read, FileShare.Read)) { //CORS請求時可訪問 Content-Length var sHeaders = response.Headers["Access-Control-Expose-Headers"] + ",Content-Length"; response.Headers.Remove("Access-Control-Expose-Headers"); response.AddHeader("Access-Control-Expose-Headers", sHeaders); long total = stream.Length;//文件總大小 response.AddHeader("Content-Length", total.ToString()); response.Charset = "UTF-8"; while (total > 0 && response.IsClientConnected) { int read = stream.Read(buffer, 0, BUFFER_SIZE);//讀取的大小 response.OutputStream.Write(buffer, 0, read); response.Flush(); total = total - read; } response.End(); } } else { response.Clear(); response.AddHeader("Access-Control-Allow-Origin", "*");//支持所有跨域請求 response.AddHeader("Access-Control-Allow-Headers", "*");//支持所有Access-Control-Request-Headers字段 response.StatusCode = 200; response.Status = "200 File_Not_Found"; response.Write("{\"Message\":\"File Not Found\",\"Status\":\"ERROR\"}"); response.End(); } } } }
測試結果:
文件准備 D:\\Test\1.txt(數據過多) D:\\Test\3.txt(數據略少) 兩個文件,文件 2.txt 不存在。