下载附件(image,doc,docx, excel,zip,pdf),应该是实际工作中经常遇到一个问题;这里使用过几种方式分享出来仅供参考; 初次写可能存在问题,有问题望指出

​ 主要了解的几个知识点:

先来介绍常用方式: 这里下载.doc文档为例,其它都类似

利用 iframe 或 a 连接

服务端代码


// nodejs
const http = require('http');
const fs = require('fs');
const path = require('path');
http.createServer(function (req, res) {
let filename = encodeURIComponent('微信多开的步骤.doc');
// 下面两个主要在跨域情况下,需要设置的
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Expose-Headers', 'Content-Disposition'); // 设置响应头
res.setHeader('Content-Type', 'application/zip;charset=UTF-8');
res.setHeader('Content-Disposition', `attachment; filename=${filename}`);
let fs.readFile(path.resolve(__dirname, `./微信多开的步骤.doc`), function (err, data) {
if (err) throw err;
res.end(data);});
}).listen(3000);

Content-Disposition 消息头指示回复的内容该以何种形式展示,是以内联的形式(即网页或者页面的一部分),还是以附件的形式下载并保存到本地。

​ 大概流程:
​ 1 下载时浏览器会尝试去找下响应头中 Content-Disposition
​ 2 如果不存在,首先尝试去预览方式打开该文件 ,如果能就直接显示否则以附件的形式下载并保存;

注意:指定在下载文件名中文情况下,必须先进行编码;

JS


// iframe
var downloadFileUrl = "http://localhost:3000"
var elemIF = document.createElement("iframe");
elemIF.src = downloadFileUrl;
elemIF.style.display = "none";
document.body.appendChild(elemIF); // a
var a = document.createElement('a');
a.href = downloadFileUrl;
a.click();

上述两种方式仅仅就是发送一个请求,主要依赖后端的支持;对不需要精确知道文件下载的状态,上面方式就能满足下载;

大家可能有疑问,iframe 不是可以通过 onload 来捕获加载的完成状态 ?
先来看看 load 适用哪些对象?

load

​ W3C 对 load 定义

Type load
Sync / Async Async
Bubbles No
Trusted Targets Window, Document, Element

适用对象:window,Document,Element 那么对于我们下载的文件并在其范围;

如果需要捕获文件下载的进度以及文件下载完成的状态,需要使用下面的方式;

XMLHttpRequest


var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onprogress = function (event) {
console.log(Math.round(event.loaded / event.total * 100) + "%");
};
xhr.responseType = 'arraybuffer';
xhr.addEventListener('readystatechange', function (event) {
if (xhr.status === 200 && xhr.readyState === 4) {
// 获取响应头主要获取附件名称
var contentDisposition = xhr.getResponseHeader('content-disposition');
// 获取类型类型和编码
var contentType = xhr.getResponseHeader('content-type');
// 构造blob对象,具体看头部提供的链接地址
var blob = new Blob([xhr.response], {
type: contentType
});
var url = window.URL.createObjectURL(blob);
// 获取文件夹名
var regex = /filename=[^;]*/;
var matchs = contentDisposition.match(regex);
if (matchs) {
filename = decodeURIComponent(matchs[0].split("=")[1]);
} else {
filename = +Date.now() + ".doc";
}
var a = document.createElement('a');
a.href = url;
a.download = filename;
a.click();
window.URL.revokeObjectURL(url);
// dosomething
}
})
xhr.send();

上述对比第一种方式,通过 onprogress 捕获下载进度(界面通过显示进度条来提升体验);通过 readystatechange 监听下载完后并可以做其它的事情;

注意: 必须指定 responseType 类型,可以是arraybuffer 或 blob 否则会出现错误问题 比如 zip,pdf文件下载之后打不开提示错误的格式; .doc,.excel文件内容乱码等;

来源:https://segmentfault.com/a/1190000017831033

最新文章

  1. jsp中运用application实现共享留言板功能
  2. import 本地Python module或package
  3. hdu 1166
  4. zepto源码--核心方法10(位置)--学习笔记
  5. Python:Python 3.x 的革新
  6. Linux下find一次查找多个指定类型文件,指定文件或者排除某类文件,在 GREP 中匹配多个关键 批量修改文件名等
  7. Jquery 等待ajax返回数据loading控件ShowLoading组件
  8. 【转】Objective-C代码注释和文档输出的工具和方法
  9. BZOJ1271: [BeiJingWc2008]秦腾与教学评估
  10. 【转】SQL多条件模糊查询解决方案-存储过程
  11. 走进 Xamarin Test Recorder for Xamarin.Forms
  12. 【转载】SDL2.0在mfc窗口中显示yuv的一种方法
  13. bzoj3295[Cqoi2011]动态逆序对 树套树
  14. input里面的submit鼠标按钮属性cursor
  15. DUILIB消息处理过程
  16. Hibernate的查询方式
  17. nsurlsessiond - taking up all bandwidth!! Help ?
  18. JavaScript -- Window-Confirm
  19. 基于Ryu的服务器实现及相关请求访问处理
  20. Python数据类型之数字

热门文章

  1. SQL内外连接的区别
  2. C#操作Excel报错:服务器出现意外情况。
  3. MSSql中profiler工具介绍,
  4. js弹出页面
  5. collides with another import statement解决办法
  6. 《Head First 设计模式》之代理模式
  7. Http和Https的区别--笔记
  8. MySQL(四)
  9. <Android 基础(十六)> Toast
  10. BarCode条形码生成库