js下載文件(兼容IE政勃、QQ)

地址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瀏覽器下載文件會(huì)崩潰
1>將window.open(sUrl, '_self');改為window.open(sUrl, '_blank');
2>判斷是否為QQ瀏覽器桨嫁,如果是,則新窗口打開當(dāng)前網(wǎng)址玻蝌。

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

使用時(shí)需傳入3個(gè)參數(shù) download(type, data, name):

  • type: 1 或 2( 用于判斷傳入的是地址還是canvas對(duì)象 )
  • data: type = 1 時(shí)傳入文件地址; type = 2 時(shí)傳入一個(gè)canvas對(duì)象( 配合html2canvas使用 )
  • name: 下載圖片默認(rèn)文件名( type = 1 時(shí)設(shè)置’'為地址默認(rèn)文件名, type = 2 時(shí) name 不能為空 )
    注:name 參數(shù)雖然只有在下載文件類型為圖片時(shí)生效俯树,但為避免出錯(cuò)都需要傳入一個(gè)值
    例:download(1, url, ‘’) 或 download(2, canvas對(duì)象, ‘圖片附件’)
import download from 'ly-downloader'

download(1, url, '文件名')

思路簡(jiǎn)介:

  • 創(chuàng)建 a 標(biāo)簽帘腹,href 傳入文件地址,download 寫上文件名许饿,觸發(fā)點(diǎn)擊事件實(shí)現(xiàn)文件另存為(設(shè)置文件名對(duì)非圖片類型文件無效)
  • 圖片類型文件使用地址下載會(huì)直接打開竹椒,需要將圖片地址利用 canvas 獲取 baase64 格式文件,再由 base64 轉(zhuǎn)換為 blob 類型米辐,最后利用URL.createObjectURL() 方法獲取 blob 文件的地址胸完,此類型地址傳入 a 標(biāo)簽可實(shí)現(xiàn)不打開直接下載
  • type = 2 這種情況是個(gè)人經(jīng)常遇到頁面截圖下載的場(chǎng)景,配合插件html2canvas 來使用非常方便翘贮,原理還是根據(jù) canvas 對(duì)象一步步轉(zhuǎn)換成 blob 對(duì)象

源碼:

'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = download;
/**
 * 下載文件
 *
 * @export
 * @param {*} type 設(shè)置接收數(shù)據(jù)類型 參數(shù) 1 或 2
 * @param {*} data type為 1 時(shí) data 為文件地址赊窥; type為 2 時(shí) data 為canvas對(duì)象
 * @param {*} name 當(dāng)文件為圖片類型時(shí)需設(shè)置文件名
 */
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 轉(zhuǎn)換位 blob 對(duì)象
 * blob 存儲(chǔ) 2進(jìn)制對(duì)象的容器
 * @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 });
}

/**
 * 將圖片地址轉(zhuǎn)換為 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;
  }
}

方式三

// 保存到本地并自動(dòng)點(diǎn)擊
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==');
    // 為了避免大文件影響用戶體驗(yàn),建議加loading
    xhr.onload = () => {
        if (xhr.status === 200) {
            // 獲取文件blob數(shù)據(jù)并保存
            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 對(duì)象
    document.body.removeChild(elink)
} else { // IE10+下載
    navigator.msSaveBlob(blob, fileName)
}

兼容性說明

谷歌和火狐支持a標(biāo)簽的download屬性狸页,ie有自帶的msSaveBlob方法锨能,或者用其他方式實(shí)現(xiàn)扯再。

下載說明

有時(shí)候你下載后發(fā)現(xiàn)直接打開了,只要不是在瀏覽器中打開址遇,就是下載完成了熄阻。有可能電腦設(shè)置了下載自動(dòng)使用某軟件打開。還可以從瀏覽器中的下載記錄去查看倔约,有記錄則下載成功秃殉,不必糾結(jié)。

相關(guān)文章

vue導(dǎo)出文件

網(wǎng)站導(dǎo)航

網(wǎng)站導(dǎo)航

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末浸剩,一起剝皮案震驚了整個(gè)濱河市钾军,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌绢要,老刑警劉巖吏恭,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異重罪,居然都是意外死亡樱哼,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門剿配,熙熙樓的掌柜王于貴愁眉苦臉地迎上來唇礁,“玉大人,你說我怎么就攤上這事惨篱。” “怎么了围俘?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵砸讳,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我界牡,道長(zhǎng)簿寂,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任宿亡,我火速辦了婚禮常遂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘挽荠。我一直安慰自己克胳,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布圈匆。 她就那樣靜靜地躺著漠另,像睡著了一般。 火紅的嫁衣襯著肌膚如雪跃赚。 梳的紋絲不亂的頭發(fā)上笆搓,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼满败。 笑死肤频,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的算墨。 我是一名探鬼主播宵荒,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼米同!你這毒婦竟也來了骇扇?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤面粮,失蹤者是張志新(化名)和其女友劉穎少孝,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體熬苍,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡稍走,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了柴底。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片婿脸。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖柄驻,靈堂內(nèi)的尸體忽然破棺而出狐树,到底是詐尸還是另有隱情,我是刑警寧澤鸿脓,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布抑钟,位于F島的核電站,受9級(jí)特大地震影響野哭,放射性物質(zhì)發(fā)生泄漏在塔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一拨黔、第九天 我趴在偏房一處隱蔽的房頂上張望蛔溃。 院中可真熱鬧,春花似錦篱蝇、人聲如沸贺待。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽狠持。三九已至,卻和暖如春瞻润,著一層夾襖步出監(jiān)牢的瞬間喘垂,已是汗流浹背甜刻。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留正勒,地道東北人得院。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像章贞,于是被迫代替她去往敵國和親祥绞。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容