美文网首页
js下载文件(兼容IE、QQ)

js下载文件(兼容IE、QQ)

作者: lesdom | 来源:发表于2019-07-17 13:09 被阅读0次

    地址URL

    方式一

    window.downloadFile = function (sUrl) {
        //iOS devices do not support downloading. We have to inform user about this.
        if (/(iP)/g.test(navigator.userAgent)) {
            alert('Your device does not support files downloading. Please try again in desktop browser.');
            return false;
        }
    
        //If in Chrome or Safari - download via virtual link click
        if (window.downloadFile.isChrome || window.downloadFile.isSafari) {
            //Creating new link node.
            var link = document.createElement('a');
            link.href = sUrl;
    
            if (link.download !== undefined) {
                //Set HTML5 download attribute. This will prevent file from opening if supported.
                var fileName = sUrl.substring(sUrl.lastIndexOf('/') + 1, sUrl.length);
                link.download = fileName;
            }
    
            //Dispatching click event.
            if (document.createEvent) {
                var e = document.createEvent('MouseEvents');
                e.initEvent('click', true, true);
                link.dispatchEvent(e);
                return true;
            }
        }
       
        // Force file download (whether supported by server).
        if (sUrl.indexOf('?') === -1) {
            sUrl += '?download';
        }
    
        window.open(sUrl, '_self');
        return true;
    }
    window.downloadFile.isChrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;
    window.downloadFile.isSafari = navigator.userAgent.toLowerCase().indexOf('safari') > -1;
    
    问题

    1、QQ浏览器下载文件会崩溃
    1>将window.open(sUrl, '_self');改为window.open(sUrl, '_blank');
    2>判断是否为QQ浏览器,如果是,则新窗口打开当前网址。

    getBrowserInfo () { 
        var ua = navigator.userAgent.toLocaleLowerCase(); 
        var browserType=null; 
        if (ua.match(/msie/) != null || ua.match(/trident/) != null) { 
            browserType = "IE"; 
            browserVersion = ua.match(/msie ([\d.]+)/) != null ? ua.match(/msie ([\d.]+)/)[1] : ua.match(/rv:([\d.]+)/)[1]; 
        } else if (ua.match(/firefox/) != null) { 
            browserType = "火狐"; 
        }else if (ua.match(/ubrowser/) != null) { 
            browserType = "UC"; 
        }else if (ua.match(/opera/) != null) { 
            browserType = "欧朋"; 
        } else if (ua.match(/bidubrowser/) != null) { 
            browserType = "百度"; 
        }else if (ua.match(/metasr/) != null) { 
            browserType = "搜狗"; 
        }else if (ua.match(/tencenttraveler/) != null || ua.match(/qqbrowse/) != null) { 
            browserType = "QQ"; 
        }else if (ua.match(/maxthon/) != null) { 
            browserType = "遨游"; 
        }else if (ua.match(/chrome/) != null) { 
            var is360 = _mime("type", "application/vnd.chromium.remoting-viewer"); 
            function _mime(option, value) { 
                var mimeTypes = navigator.mimeTypes; 
                for (var mt in mimeTypes) { 
                    if (mimeTypes[mt][option] == value) { 
                        return true; 
                    } 
                } 
                return false; 
            } 
            if(is360){ 
                browserType = '360'; 
            }else{ 
                $('html').css("zoom",".80"); 
            } 
        }else if (ua.match(/safari/) != null) { 
            browserType = "Safari"; 
        } 
        return browserType
    },
    
    downloadFile(url) 
    if (this.getBrowserInfo() === 'QQ') {        
      const { href } = this.$router.resolve({
          name: "donation",            
      });
      window.open(href, '_blank');
    } 
    

    2、IE浏览器接口没获取到链接地址
    所以我把下载的地址写死了

    window.location.origin + '/api/web/fundMessagePublic/download?id=' + id
    

    兼容IE

    判断

    window.downloadFile.isIE = function () { 
    if(!!window.ActiveXObject || "ActiveXObject" in window) 
        return true; 
    else 
        return false; 
    }
    

    方式1

    if (window.downloadFile.isIE()) {
        var elemIF = document.createElement("iframe");  
        elemIF.src = sUrl;  
        elemIF.style.display = "none";  
        document.body.appendChild(elemIF);
        elemIF.click()   
    }
    

    方式2

    if (window.navigator.msSaveBlob) {
        try {
            window.navigator.msSaveBlob(url, downloadFileName);
        }
        catch (e) {
            console.log(e);
        }
    }
    

    方式二

    npm install --save ly-downloader
    

    使用时需传入3个参数 download(type, data, name):

    • type: 1 或 2( 用于判断传入的是地址还是canvas对象 )
    • data: type = 1 时传入文件地址; type = 2 时传入一个canvas对象( 配合html2canvas使用 )
    • name: 下载图片默认文件名( type = 1 时设置’'为地址默认文件名, type = 2 时 name 不能为空 )
      注:name 参数虽然只有在下载文件类型为图片时生效,但为避免出错都需要传入一个值
      例:download(1, url, ‘’) 或 download(2, canvas对象, ‘图片附件’)
    import download from 'ly-downloader'
    
    download(1, url, '文件名')
    

    思路简介:

    • 创建 a 标签,href 传入文件地址,download 写上文件名,触发点击事件实现文件另存为(设置文件名对非图片类型文件无效)
    • 图片类型文件使用地址下载会直接打开,需要将图片地址利用 canvas 获取 baase64 格式文件,再由 base64 转换为 blob 类型,最后利用URL.createObjectURL() 方法获取 blob 文件的地址,此类型地址传入 a 标签可实现不打开直接下载
    • type = 2 这种情况是个人经常遇到页面截图下载的场景,配合插件html2canvas 来使用非常方便,原理还是根据 canvas 对象一步步转换成 blob 对象

    源码:

    'use strict';
    
    Object.defineProperty(exports, "__esModule", {
      value: true
    });
    exports.default = download;
    /**
     * 下载文件
     *
     * @export
     * @param {*} type 设置接收数据类型 参数 1 或 2
     * @param {*} data type为 1 时 data 为文件地址; type为 2 时 data 为canvas对象
     * @param {*} name 当文件为图片类型时需设置文件名
     */
    function download(type, data, name) {
      if (type == 1) {
        var url = data;
        // 通过地址判断是否为图片类型文件
        var ext = url.slice(url.lastIndexOf('.') + 1).toLowerCase();
        if (isImage(ext)) {
          convertUrlToBase64(url).then(function (base64) {
            var blob = convertBase64UrlToBlob(base64);
            // 下载
            if (myBrowser() == 'IE') {
              window.navigator.msSaveBlob(blob, name + '.jpg');
            } else {
              var a = document.createElement('a');
              a.download = name;
              a.href = URL.createObjectURL(blob);
              a.click();
            }
          });
        } else {
          var a = document.createElement('a');
          a.download = name;
          a.href = url;
          a.click();
        }
      } else {
        var dataURL = data.toDataURL('image/jpeg', 1.0);
        var base64 = {
          dataURL: dataURL,
          type: 'image/jpg',
          ext: 'jpg'
        };
        var blob = convertBase64UrlToBlob(base64);
        // 下载
        if (myBrowser() == 'IE') {
          window.navigator.msSaveBlob(blob, name + '.jpg');
        } else {
          var _a = document.createElement('a');
          _a.download = name;
          _a.href = URL.createObjectURL(blob);
          _a.click();
        }
      }
    }
    
    /**
     * 将 base64 转换位 blob 对象
     * blob 存储 2进制对象的容器
     * @export
     * @param {*} base64
     * @returns
     */
    function convertBase64UrlToBlob(base64) {
      var parts = base64.dataURL.split(';base64,');
      var contentType = parts[0].split(':')[1];
      var raw = window.atob(parts[1]);
      var rawLength = raw.length;
      var uInt8Array = new Uint8Array(rawLength);
      for (var i = 0; i < rawLength; i++) {
        uInt8Array[i] = raw.charCodeAt(i);
      }
      return new Blob([uInt8Array], { type: contentType });
    }
    
    /**
     * 将图片地址转换为 base64 格式
     *
     * @param {*} url
     */
    function convertUrlToBase64(url) {
      return new Promise(function (resolve, reject) {
        var img = new Image();
        img.crossOrigin = 'Anonymous';
        img.src = url;
        img.onload = function () {
          var canvas = document.createElement('canvas');
          canvas.width = img.width;
          canvas.height = img.height;
          var ctx = canvas.getContext('2d');
          ctx.drawImage(img, 0, 0, img.width, img.height);
          var ext = img.src.substring(img.src.lastIndexOf('.') + 1).toLowerCase();
          var dataURL = canvas.toDataURL('image/' + ext);
          var base64 = {
            dataURL: dataURL,
            type: 'image/' + ext,
            ext: ext
          };
          resolve(base64);
        };
      });
    }
    
    // 判断浏览器类型 
    function myBrowser() {
      var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串
      if (userAgent.indexOf("OPR") > -1) {
        return "Opera";
      }; //判断是否Opera浏览器 OPR/43.0.2442.991
      if (userAgent.indexOf("Firefox") > -1) {
        return "FF";
      } //判断是否Firefox浏览器  Firefox/51.0
      if (userAgent.indexOf("Trident") > -1) {
        return "IE";
      } //判断是否IE浏览器  Trident/7.0; rv:11.0
      if (userAgent.indexOf("Edge") > -1) {
        return "Edge";
      } //判断是否Edge浏览器  Edge/14.14393
      if (userAgent.indexOf("Chrome") > -1) {
        return "Chrome";
      } // Chrome/56.0.2924.87
      if (userAgent.indexOf("Safari") > -1) {
        return "Safari";
      } //判断是否Safari浏览器 AppleWebKit/534.57.2 Version/5.1.7 Safari/534.57.2
    }
    
    // 判断文件是否为图片类型
    function isImage(ext) {
      if (ext == 'png' || ext == 'jpg' || ext == 'jpeg' || ext == 'gif' || ext == 'bmp') {
        return true;
      }
    }
    

    方式三

    // 保存到本地并自动点击
    function saveAs(data, name) {
        const urlObject = window.URL || window.webkitURL || window;
        const export_blob = new Blob([data]);
        const save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
        save_link.href = urlObject.createObjectURL(export_blob);
        save_link.download = name;
        save_link.click();
    }
    // 下载含有url的文件
    function downloadUrlFile(url, fileName) {
        const url2 = url.replace(/\\/g, '/');
        const xhr = new XMLHttpRequest();
        xhr.open('GET', url2, true);
        xhr.responseType = 'blob';
        //xhr.setRequestHeader('Authorization', 'Basic a2VybWl0Omtlcm1pdA==');
        // 为了避免大文件影响用户体验,建议加loading
        xhr.onload = () => {
            if (xhr.status === 200) {
                // 获取文件blob数据并保存
                saveAs(xhr.response, fileName);
            }
        };
        xhr.send();
    }
    downloadUrlFile(url, fileName);
    

    文件流

    const content = res.data;
    const blob = new Blob([content])
    const fileName = decodeURI(res.headers['content-disposition'].split(';')[1].split('=')[1]) || '文件.xlsx'            
    if ('download' in document.createElement('a')) { // 非IE下载
        const elink = document.createElement('a')
        elink.download = fileName
        elink.style.display = 'none'
        elink.href = URL.createObjectURL(blob)
        document.body.appendChild(elink)
        elink.click()
        URL.revokeObjectURL(elink.href) // 释放URL 对象
        document.body.removeChild(elink)
    } else { // IE10+下载
        navigator.msSaveBlob(blob, fileName)
    }
    

    兼容性说明

    谷歌和火狐支持a标签的download属性,ie有自带的msSaveBlob方法,或者用其他方式实现。

    下载说明

    有时候你下载后发现直接打开了,只要不是在浏览器中打开,就是下载完成了。有可能电脑设置了下载自动使用某软件打开。还可以从浏览器中的下载记录去查看,有记录则下载成功,不必纠结。

    相关文章

    vue导出文件

    网站导航

    网站导航

    相关文章

      网友评论

          本文标题:js下载文件(兼容IE、QQ)

          本文链接:https://www.haomeiwen.com/subject/ecdqlctx.html