一波三折的文件下载史

497 阅读1分钟

接到一个需求,其中有一个功能是实现下载图片和文件,我一看,这应该简单吧,用a标签的download属性或者window.open()就可以,没想到后端传回来的不是Blob,而是普通的url,不管是window.open(),还是a的download属性,对于可以打开的链接,他们是不会去下载的。。那就试试将普通的url转化成base64或者Blob这种他们不认识的形式?还好网上有相关代码,改造了一下,代码如下

  图片转base64
 function image2base64(img) {  
  const canvas = document.createElement("canvas");  
  canvas.width = img.width;  
  canvas.height = img.height;  
  const ctx = canvas.getContext("2d");  
  ctx.drawImage(img, 0, 0, img.width, img.height);  
  const mime = img.src.substring(img.src.lastIndexOf(".")+1).toLowerCase();  
  const dataUrl = canvas.toDataURL("image/" + mime);  
  return dataUrl;
 }
 // 如果是blob数据,可以直接用这个函数
 function download (blob, filename) {
    const a = document.createElement('a');
    const URL = window.URL || window.webkitURL;
    const herf = URL.createObjectURL(blob);
    a.href = herf;
    a.download = filename;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    window.URL.revokeObjectURL(herf);
   };
  <script>
  function downSource(list) {
      //如果是文件类型的可以直接下载
      if(){
        const a = document.createElement('a');
         a.href = list.url;
         a.download = list.name;
         document.body.appendChild(a);
         a.click();
         document.body.removeChild(a);
      } else {
         // 如果是图片类型的需要转化成blob的形式
        const image = new Image();
        image.setAttribute("crossOrigin",'use-credentials');
        image.src = '../files/test-download.png' + '?' + new Date().getTime();
        image.onload = function() {  
        const imageDataUrl = image2base64(image);  
        const imageBlobData = dataUrl2Blob(imageDataUrl);
        download(imageBlobData, list.name);
      }    
      }
  }
  
</script>

本以为可以大功告成了,没想到下载文件的时候filename没起作用~查了一下,segmentfault.com/q/101000002…

可能需要后端设置一下。嗯~有点麻烦啊,向其他小姐姐求助,她只说了几个字,用xhr和blob,我一试还真行,代码也精简了很多

const request = (list) => {
    const req = new XMLHttpRequest();
    req.open('GET', list.url, true);
    req.responseType = 'blob';
    req.setRequestHeader('Content-Type', 'application/json');
    req.onload = () => {
      const data = req.response;
      const blob = new Blob([data]);

      if (window.navigator && window.navigator.msSaveOrOpenBlob) { //这是为了兼容ie浏览器,否则点击没有效果
        window.navigator.msSaveBlob(blob, list.name);
      } else {
        const blobUrl = window.URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.download = list.name;
        a.href = blobUrl;
        a.click();
      }
    };
    req.send(null);
  };

ok,结束~