前言
踩过的坑
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.txtspan> <span id="progress1">span>
li>
<li>
<span>文件2.txtspan> <span id="progress2">span>
li>
<li>
<span>文件3.txtspan> <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 不存在。