ie 打开后端发过来的pdf_JS如何下载资源文件,并且兼容IE、Edge

前言:这边需要做一个功能: 点击按钮,下载所有的资源文件。

0fc23a0fcd2cef730211fe1ce929356f.png

这不挺简单,心想,直接通过 a.download 直接解决不就 ok 了。谁知...

我尿了... 对不起,是我年轻了。

与后台确定了一下返回的数据,这边后台会返回一个 资源链接 和 资源名。我们通过这个资源链接,去浏览器中输入,是可以查看的。

于是我兴致勃勃的通过 a.download 去下载,发现,问题出现了

下载下来的不知道是什么鸡儿玩意,根本无法打开,文件损坏

baccb6182e8b257a47c70359964ea2c0.png

再理理思路

首先确保这个文件是否可以下载

例如我们的图片资源是 : httpp://images/b532cecf17544c7784c321937eaaba20 (故意打错https)

然后我们给他加个attname : httpp://www.baidu.com/images/b532cecf17544c7784c321937eaaba20?attname=test.jpg(故意打错https)

发现,通过这种方式,下载后就可以正常打开了,如果直接下载,那就会报 

根本无法打开,文件损坏

618897eebfd455d413e335c28bbb3bf6.png

最终解决

通过 download 属性指定下载的名字,然后模拟一个点击事件。

function downloadURL(url, name = '') {  const link = document.createElement('a');  link.download = name;  link.href = url;  document.body.appendChild(link);  link.click();  document.body.removeChild(link);}

但是呢,有问题。来看看有啥问题,首先,这个兼容性上,就有问题了。可以看到 ie 不支持,低版本的 ios safari 也不行,兼容性问题。

dcc18de4992f101d1e1768161bc828fe.png

我们可通过 Blob 二进制对象进行下载。

最终,通过 Chrome、FireFox、360 均可下载,但在 IE 和 Edge 中就不行,但是也没报错。

通过查询资料,发现 IE / Edge 和高大上的 Chrome /Firefox 对于 window.URL.createObjectURL 创建 Blob 链接最直观的区别在于 : 得到的 blob 链接形式不一样

Chrome 和 Firefox 会生成的带有当前域名的标准 blob 链接形式(例如 https : //www.baidu.com/86e01467-6654-4b74-98b3-ca25f396bc2f)

而 IE 和 Edge 会生成的不带域名的 blob 链接(例如 242CACD6-06D5-4145-A6DA-55DBE47409DB),所以如果用上面代码的方式,是下载不了文件的,并且浏览器也不会报错。

解决方案 : 使用 window.navigator.msSaveOrOpenBlob(blob, filename),代替 window.URL.createObjectURL

相关代码

/** * @desc 资源下载文 件 * @Support Image/Audio/Video/Word/PDF * @param {Object} resource - 资源文件 * resource: { *     link: '', 文件下载地址 *     reName: '', 用户自定义导出的文件名 *     fileType: '', 源文件类型,当文件名为空或不携带类型时,此字段必须需要 *     fileName: '', 源文件名,尽可能带有类型,如 a.jpg、b.mp3 * } */function fetchBlob(url) {  return new Promise((resolve, reject) => {    let xhr = new XMLHttpRequest();    xhr.open('GET', url);    xhr.responseType = 'blob';    xhr.onload = function() {      if (xhr.status === 200) {        resolve(xhr.response);      } else {        reject(new Error(xhr.statusText || 'Download failed.'));      }    };    xhr.onerror = function() {      reject(new Error('Download failed.'));    };    xhr.send();  });}function downloadURL(url, name = '') {  const link = document.createElement('a');  link.download = name;  link.href = url;  if ('download' in document.createElement('a')) {    document.body.appendChild(link);    link.click();    document.body.removeChild(link);  } else {    // 对不支持download进行兼容    click(link, (link.target = '_blank'));  }}// 参考 FileSaver.js ,链接地址// https://github.com/eligrey/FileSaver.js/blob/master/src/FileSaver.jsfunction click(node) {  try {    node.dispatchEvent(new MouseEvent('click'));  } catch (e) {    let evt = document.createEvent('MouseEvents');    console.log(evt);    evt.initMouseEvent(      'click',      true,      true,      window,      0,      0,      0,      80,      20,      false,      false,      false,      false,      0,      null    );    node.dispatchEvent(evt);  }}/** * @desc 拼接下载链接 * 添加 attname 属性用于下载资源文件 */function retrieveReallyLink(link, name) {  let originUrl = `${link}?attname=${name}`;  if (/\?/.test(link)) {    originUrl = `${link}&attname=${name}`;  }  return originUrl;}/** * @desc 处理文件名 * 1,用户自定义导出的文件名reName为准,无reName,以fileName为准,无fileName,给定默认文件名 * 2. type类型以fileName的为主,fileName不存在或不携带类型,则以传入的 fileType 为主 */function retrieveReallyName(resource) {  const { fileName = '', fileType = '', reName = '' } = resource;  let type = fileType;  let originName = '';  if (fileName && fileName.indexOf('.') > -1) {    type = fileName.substring(fileName.lastIndexOf('.')).toLowerCase();  }  if (reName) {    originName = `${reName}${type}`;  } else if (fileName) {    originName =      fileName.indexOf('.') > -1 ? `${fileName}` : `${fileName}${type}`;  } else {    originName = `新建下载文件${type}`;  }  return originName;}/** * @desc 资源下载 * @param {Object} resource */export function downloadFile(resource) {  const { link = '' } = resource;  const originName = retrieveReallyName(resource);  const originUrl = retrieveReallyLink(link, originName);  return fetchBlob(originUrl)    .then(resp => {      if (resp.blob) {        return resp.blob();      } else {        return new Blob([resp]);      }    })    .then(blob => {      if ('msSaveOrOpenBlob' in navigator) {        window.navigator.msSaveOrOpenBlob(blob, originName);      } else {        const obj = URL.createObjectURL(blob);        downloadURL(obj, originName);        URL.revokeObjectURL(obj);      }    })    .catch(err => {      throw new Error(err.message);    });}/** * @desc 获取文件类型,当后台文件名为空或不携带类型时,需要通过此方法获取文件类型 * @param {Number} resourceType 资源类型,参考 constant 文件定义的resoureType */export function retrieveFileType(resourceType) {  let resultType = '';  switch (resourceType) {    case 1:      resultType = '.mp4';      break;    case 2:      resultType = '.png';      break;    case 3:      resultType = '.doc';      break;    case 4:      resultType = '.ppt';      break;    case 5:      resultType = '.mp3';      break;    case 8:      resultType = '.pdf';      break;    default:      break;  }  return resultType;}

最终效果图

365cdea323d200e863c447e8f0049765.png

23963da00272168cf0454c4725511e27.png

2e845765d48fdc80613a88134984d2f7.png

da19ea1a7f05a80344f867f499c117db.png

友情链接

  • FileSaver.js

    https://github.com/eligrey/FileSaver.js/blob/master/src/FileSaver.js

  • 知乎-js如何下载图片、pdf、mp3等各类多媒体文件

    https://zhuanlan.zhihu.com/p/77529101

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值