H5+Ajax+WebApi实现文件下载(进度条,多文件)
前言
踩过的坑
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 = ;
- [HttpPost]
- public void DownloadFileUrl(dynamic args)
- {
- string url = args.url;
- string filename = url.Substring(url.LastIndexOf('\\') + );
- 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 > && response.IsClientConnected)
- {
- int read = stream.Read(buffer, , BUFFER_SIZE);//读取的大小
- response.OutputStream.Write(buffer, , 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 = ;
- 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 不存在。
H5+Ajax+WebApi实现文件下载(进度条,多文件)的更多相关文章
- Ajax实现带进度条的文件上传
Ajax实现带进度条的文件上传 文件上传页面运行效果 上传文件并显示进度条运行效果 代码如下; DiskFileItemFactory factory = new DiskFileItemFactor ...
- jQuery ajax 标准写法及进度条绘制
jQuery ajax 标准写法及进度条绘制 $.ajax({ url: "http://www.microsoft.com", //请求的url地址 dataType: &quo ...
- Python展示文件下载进度条
前言 大家在用Python写一些小程序的时候,经常都会用到文件下载,对于一些较小的文件,大家可能不太在乎文件的下载进度,因为一会就下载完毕了. 但是当文件较大,比如下载chromedriver的时候, ...
- cordova加载层、进度条、文件选择插件
在做cordova项目的时候,感觉应用的响应速度跟原生应用比相差甚远,一个主要问题就是如加载层.进度条等弹出对话框的效率不行.毕竟项目中的这些弹框都是用dom拼成的,dom的渲染效率和原生控件比起来慢 ...
- ajax页面加载进度条插件
下面两个都是youtube视频的加载进度条效果的ajax插件 一.官网:http://ricostacruz.com/nprogress/官网 github:https://github.com/rs ...
- 给H5页面添加百分比的进度条,精确度高
进度条样式地址:http://sandbox.runjs.cn/show/6vxbxjrf SVG圆环样式地址:http://sandbox.runjs.cn/show/3ho1qpe9 原理:由于H ...
- asp.net利用ajax和jquery-ui实现进度条
前台用ajax不停进行查询,直到任务完成.进度条用的是jquery-ui.后台用一般处理程序处理相应,进度信息保存在HttpContext.Application中. 代码作为简单示例,实际应用时应对 ...
- Ajax技术——带进度条的文件上传
1.概述 在实际的Web应该开发或网站开发过程中,经常需要实现文件上传的功能.在文件上传过程中,经常需要用户进行长时间的等待,为了让用户及时了解上传进度,可以在上传文件的同时,显示文件的上传进度条.运 ...
- H5 可堆叠的圆环进度条,支持任意数量子进度条
by Conmajia SN: S22-W1M 由来 看到一篇帖子<vue实用组件--圆环百分比进度条>,让我想起了很多年前我在WinForm下仿制过的Chrome进度条. ▲ 原版进度条 ...
随机推荐
- AsyncLocal的运作机制和陷阱
这是今天帮柠檬分析一个AsyncLocal相关的问题时发现的. 试想这个代码输出的值是多少? using System; using System.Threading; using System.Th ...
- iOS10 相册权限
当我升级到Xcode8后,启动我的相机项目,直接crash,输出的日志如下: '2016-07-08 16:41:11.268943 project-name[362:56625] [MC] Syst ...
- 深入分析JavaWeb技术内幕(修订版)》【PDF】下载
<深入分析JavaWeb技术内幕(修订版)>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230062569 内容简介 <深入分析 ...
- 《Spark大数据处理:技术、应用与性能优化》【PDF】 下载
内容简介 <Spark大数据处理:技术.应用与性能优化>根据最新技术版本,系统.全面.详细讲解Spark的各项功能使用.原理机制.技术细节.应用方法.性能优化,以及BDAS生态系统的相关技 ...
- 自定义结构化config文件
前言 开发过程中我们会经常使用到各种config文件,经常我们会使用appSettings进行设置所用的配置,但是随着配置量的增多,都放在appSettings里面明显是不合适的,一方面配置容易混乱, ...
- Appsacn 定期自动化扫描
appscan提供了计划扫描的选项,配合windows的计划任务,可以按需设定. 操作流程如下: 1.打开Appsacn--工具---扫描调度程序---新建 2.新建后显示如下窗口 3.填写好相应的设 ...
- 微信小程序开发模板消息的时候 出现 errcode: 41028, errmsg: "invalid form id hint:
小程序开发模板消息的时候 出现 errcode: 41028, errmsg: "invalid form id hint: 我是使用的微信支付发送模板消息,提示的formid无效的 大家 ...
- 房上的猫:JavaDoc注释
//这是一个注释 /* *这是一个演示程序 */ /** *@这是JavaDoc注释. */ JavaDoc注释 背景: javadoc是Sun公司提供的一个技术,它从程序源代码中抽 ...
- Pyhon学习_04_字典、集合
字典.集合两种基本类型都是通过映射的方式访问. 字典 python中的字典和perl中的哈希是很相似的,包括其重要的几条属性: 1. 键值必须是唯一的 2. 键值必须是可哈希的,也就是键值不能够是可变 ...
- C程序设计语言(第二版)--- 习题选
1. 解: 2. 解: 3. (分析的好有条理啊!) 4. 解: