一个PC端的项目(vue),开发是在google浏览器测试的,刚开始是使用的以下代码实现文件下载,图片,pdf,doc等:

openDownload(link, name) {
      const x = new XMLHttpRequest();
      x.open('GET', link, true);
      x.responseType = 'blob';
      x.onload = function () {
        const url = window.URL.createObjectURL(x.response);
        const a = document.createElement('a');
        a.href = url;
        a.download = name || '';
        a.click();
      };
      x.send();
    },

在google浏览器中,这个方法已经可以完成上诉的各类文件的下载。当我使用360家的两款浏览器测试的时候,发下下载图片会报跨域,然后想起之前H5端使用canvas处理跨域下载的方法,此处用上,更改后的代码如下:


    async openDownload(urls, name) {
      const link = urls;
      const files = link.split('.');
      const type = files[files.length - 1];
      const x = new XMLHttpRequest();
      if (['jpg', 'png', 'jpeg', 'gif'].includes(type)) { // 图片
        const image = await this.getBase64Image(link);
        x.open('GET', image, true);
      } else { // 非图片
        x.open('GET', link, true);
      }

      x.responseType = 'blob';
      x.onload = function () {
        const url = window.URL.createObjectURL(x.response);
        const a = document.createElement('a');
        a.href = url;
        a.download = name || '';
        a.click();
      };
      x.send();
    },
    // 图片转base64
    getBase64Image(img) {
      return new Promise((resolve, reject) => {
        if (!img) {
          reject(new Error(null));
        }
        const canvas = document.createElement('canvas');
        const image = new Image();
        image.setAttribute('crossOrigin', 'anonymous');
        image.src = `${img}?v=${Math.random()}`;
        image.onload = () => {
          canvas.width = image.width;
          canvas.height = image.height;
          const ctx = canvas.getContext('2d');
          ctx.drawImage(image, 0, 0, image.width, image.height);
          const ext = image.src.substring(image.src.lastIndexOf('.') + 1).toLowerCase();
          resolve(canvas.toDataURL(`image/${ext}`));
        };
        image.error = () => {
          reject(new Error(null));
        };
      });
    },

以上代码可以在google中实现完美下载,但是测试其他浏览器的时候,特别是ie和360的兼容模式,发现gg了。
和同事商量讨论的半天,终于得出以下解决方案:


    openDownload(urls, name) {
      const link = urls;
      const lastIndex = link.split('.').length - 1;
      const type = link.split('.')[lastIndex];
      if (['jpg', 'png', 'jpeg', 'gif'].includes(type)) { // 图片
        this.getBase64Image2(link, (image) => {
          this.XMLHttpRequest(image, `${name}.${type}`, 'image');
        });
      } else { // 非图片
        this.XMLHttpRequest(link, name, 'file');
      }
    },
    XMLHttpRequest(link, name, type) {
      console.log(name);
      const x = new XMLHttpRequest();
      x.open('GET', link, true);
      x.responseType = 'blob';
      x.onload = function () {
        console.log('onload');
        const blob = x.response;
        const url = window.URL.createObjectURL(blob);
        // 判断是否是IE浏览器
        if (window.navigator.msSaveBlob) {
          try {
            window.navigator.msSaveBlob(type === 'image' ? link : blob, name);
          } catch (e) {
            console.log(e);
          }
        } else {
          const a = document.createElement('a');
          a.href = url;
          a.download = name || '';
          a.click();
        }
      };
      x.send();
    },
    getBase64Image2(img, cb) {
      const canvas = document.createElement('canvas');
      const image = new Image();
      image.setAttribute('crossOrigin', 'anonymous');
      image.src = `${img}?v=${Math.random()}`;
      image.onload = () => {
        canvas.width = image.width;
        canvas.height = image.height;
        const ctx = canvas.getContext('2d');
        ctx.drawImage(image, 0, 0, image.width, image.height);
        const ext = image.src.substring(image.src.lastIndexOf('.') + 1).toLowerCase();
        const base64 = canvas.toDataURL(`image/${ext}`);
        if (window.navigator.msSaveBlob) { // IE
          this.dataURLtoBlob(base64, (blob) => {
            cb(blob);
          });
        } else { // 非IE
          cb(base64);
        }
      };
    },
    dataURLtoBlob(base64, cb) {
      const arr = base64.split(',');
      const bstr = atob(arr[1]);
      let n = bstr.length;
      const u8arr = new Uint8Array(n);
      while (n > 0) {
        n -= 1;
        u8arr[n] = bstr.charCodeAt(n);
      }
      const blob = new Blob([u8arr]);
      cb(blob);
    },

测试结果(UC急速有知道为啥的吗?)
在这里插入图片描述

Logo

前往低代码交流专区

更多推荐