JS下载文件经常使用的方式

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

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

先来介绍经常使用方式: 这里下载.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();

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

你们可能有疑问,iframe 不是能够经过 onload 来捕获加载的完成状态 ?
先来看看 load 适用哪些对象?ui

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文件内容乱码等;

相关文章
相关标签/搜索