JS 下載文件方法分享(解決圖片文件無法直接下載和 IE兼容問題)

場景簡介

由于業(yè)務需要,經(jīng)常遇到下載各類文件的需求嫌褪,其中最頭疼的莫過于前端下載圖片了旦部,直接給個圖片文件地址會變成直接打開圖片祈搜,而不是彈窗提示另存為,研究了下前端實現(xiàn)文件下載最便捷的方法還是創(chuàng)建 a 標簽士八,寫入download 屬性實現(xiàn)點擊下載容燕,但這在 ie 瀏覽器上的實現(xiàn)又與一般瀏覽器不同,于是摸索之后寫了個通用的下載方法婚度,既可用來下載文件也可下載圖片蘸秘,希望能夠幫到大家。

npm 安裝使用

npm install --save ly-downloader

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

  • type: 1 或 2( 用于判斷傳入的是地址還是canvas對象 )
  • data: type = 1 時傳入文件地址蝗茁; type = 2 時傳入一個canvas對象( 配合html2canvas使用 )
  • name: 下載圖片默認文件名( type = 1 時設置''為地址默認文件名, type = 2 時 name 不能為空 )
    注:name 參數(shù)雖然只有在下載文件類型為圖片時生效醋虏,但為避免出錯都需要傳入一個值
    例:download(1, url, '') 或 download(2, canvas對象, '圖片附件')

以 Vue 中組件使用為例

import download from 'ly-downloader'
export default {
  methods: {
    // url = '你的文件地址'
    _download (url) {
      download(1, url, '文件名')
    },
  }
}

思路簡介

  • 創(chuàng)建 a 標簽,href 傳入文件地址哮翘,download 寫上文件名颈嚼,觸發(fā)點擊事件實現(xiàn)文件另存為(設置文件名對非圖片類型文件無效)
  • 圖片類型文件使用地址下載會直接打開,需要將圖片地址利用 canvas 獲取 baase64 格式文件饭寺,再由 base64 轉(zhuǎn)換為 blob 類型阻课,最后利用URL.createObjectURL() 方法獲取 blob 文件的地址,此類型地址傳入 a 標簽可實現(xiàn)不打開直接下載
  • type = 2 這種情況是個人經(jīng)常遇到頁面截圖下載的場景艰匙,配合插件html2canvas 來使用非常方便限煞,原理還是根據(jù) canvas 對象一步步轉(zhuǎn)換成 blob 對象

源碼

'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = download;
/**
 * 下載文件
 *
 * @export
 * @param {*} type 設置接收數(shù)據(jù)類型 參數(shù) 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.style.display = 'none'
          document.body.appendChild(a);
          a.click();
          document.body.removeChild(a);
        }
      });
    } else {
      var a = document.createElement('a');
      a.download = name;
      a.href = url;
      a.style.display = 'none'
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
    }
  } 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.style.display = 'none'
      document.body.appendChild(_a);
      _a.click();
      document.body.removeChild(_a);
    }
  }
}

/**
 * 將 base64 轉(zhuǎn)換位 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 });
}

/**
 * 將圖片地址轉(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;
  }
}
好啦员凝,希望該方法能夠解決大家在下載文件特別是圖片時遇到的問題 ^ - ^
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末署驻,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子健霹,更是在濱河造成了極大的恐慌旺上,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件骤公,死亡現(xiàn)場離奇詭異,居然都是意外死亡扬跋,警方通過查閱死者的電腦和手機阶捆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人洒试,你說我怎么就攤上這事该窗∽菏茫” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長亦渗。 經(jīng)常有香客問我,道長柠逞,這世上最難降的妖魔是什么套像? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮乖订,結果婚禮上扮饶,老公的妹妹穿的比我還像新娘。我一直安慰自己乍构,他們只是感情好甜无,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著哥遮,像睡著了一般岂丘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上眠饮,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天奥帘,我揣著相機與錄音,去河邊找鬼君仆。 笑死翩概,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的返咱。 我是一名探鬼主播钥庇,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼咖摹!你這毒婦竟也來了评姨?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤萤晴,失蹤者是張志新(化名)和其女友劉穎吐句,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體店读,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡嗦枢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了屯断。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片文虏。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡侣诺,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出氧秘,到底是詐尸還是另有隱情年鸳,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布丸相,位于F島的核電站搔确,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏灭忠。R本人自食惡果不足惜膳算,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望更舞。 院中可真熱鬧畦幢,春花似錦、人聲如沸缆蝉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽刊头。三九已至黍瞧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間原杂,已是汗流浹背印颤。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留穿肄,地道東北人年局。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像咸产,于是被迫代替她去往敵國和親矢否。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

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