移動端H5下載文件

前段時間遇到一個需求,需要在H5頁面中增加下載文件按鈕,下載一個壓縮文件,第一個想到的當然是最普遍和常用的方法:動態生成a標籤,把鏈接地址給到href屬性,觸發一個click事件,完美下載。於是擼起袖子就開幹。

由於文件數據是通過接口請求回來的數據流,application/octet-stream類型,需要轉換一下來使用:

         download() {
            let blob = res.data;
            // 請求文件數據,返回類型爲blob數據流,類型application/octet-stream
            let url = window.URL.createObjectURL(blob); // 將blob轉換爲數據連接地址
            let a = document.createElement('a');
            a.download = 'test.zip';
            a.href = url;
            a.target = '_blank';
            document.appendChild(a);
            a.click();
            document.removeChild(a);
        }

在pc上調試時很好,下載沒有任何問題,但是放到真機上就一堆問題來了:

iOS系統點擊就沒反應,根本沒法下載,安卓手機也是幾乎所有瀏覽器都有問題,要麼下載的文件後綴不對,要麼沒法下載,全軍覆沒。

網上查了下,H5下載文件失敗幾乎是普遍問題,只有圖片是沒有兼容性問題的,長按保存本地,但是文件很多頁的時候就不現實了,幾乎沒有什麼體驗可言。還有的是說ios是極度封閉的環境,下載東西很麻煩,不好處理。

於是又開始嘗試其它辦法

1、file-saver插件

npm i file-saver -S

使用:

import fileSaver from 'file-saver';
、、、
 let blob = res.data;
// 請求文件數據,返回類型爲blob數據流,類型application/octet-stream
let url = window.URL.createObjectURL(blob); // 將blob轉換爲數據連接地址
fileSaver.saveAs(url,'test.zip');

結果證明效果是一樣的,真機上下載不了。

2、file-saver + jszip

安裝jszip:

npm i jszip -S

使用:

import jsZip from 'jszip';

import { saveAs } from 'file-saver';
、、、
let zip = new jsZip();
var myFile = zip.folder(); // 新建一個文件夾
let fileReader = new FileReader();
fileReader.onload = function(e) {
    let base64 = e.target.result;
    myFile.file('test.zip', base64, {
         base64: true
    }); // 文件名稱

    zip.generateAsync({ type: 'blob' }).then(function(content) {
         // see FileSaver.js
          saveAs(content, 'test.zip');
    });
}
fileReader.readAsDataURL(blob);

效果依舊、、、失敗

3、直接嘗試着使用絕對地址來做測試,直接下載一個服務器上的壓縮文件

download() {
   let url = htts://xxxxxx/zzz.zip; // 絕對地址
   let a = document.createElement('a');
   a.download = 'test.zip';
   a.href = url;
   a.target = '_blank';
   document.appendChild(a);
   a.click();
   document.removeChild(a);
}

真機調試,毫無兼容性問題,安卓和ios的各個瀏覽器都沒問題,只有uc瀏覽器不支持打開zip文件而彈出提示,無法下載,所以思路就有了:

讓後臺把文件壓縮好,生成一個絕對路徑地址,然後把路徑給到前臺下載。

方法有兩種:

1、文件放到七牛雲上,生成絕對地址下載,但是這地址沒加權限,任何人拿到都可以下載,對於合同文件類型的資源來說不夠安全,放棄。

2、放到自己服務器上,依然生成絕對地址,給鏈接地址設置時效性,超過時間則清空服務器資源,使得下載鏈接無效,也可以很好的節約文件服務器資源。

3、放到自己服務器上,給鏈接做權限校驗,前端根據後臺給到的規則拼接地址,最後加上token作爲權限校驗

由於這個項目做了三級等保功能,討論後決定使用第3種方案,和三級等保無縫切合。

代碼:

         download() {
            let url = `${location.origin}/xxxx/${this.fileCode}?token=${this.token}`; // 拼接下載地址
            let a = document.createElement('a');
            a.download = 'test.zip';
            a.href = url;
            a.target = '_blank';
            document.appendChild(a);
            a.click();
            document.removeChild(a);
        }

這個方法雖然不能說完美,但至少能兼容絕大部分主流瀏覽器和移動端操作系統了,基本上能滿足大部分項目的需求。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章