h5實現下載(一)h5頁面如何下載圖片、文本等


需求

有一個H5頁面,頁面中有個“點擊下載”的按鈕,點擊之后,完成下載特定的apk或者txt等其他類型文件(微信好坑,各種限制,基本上從微信瀏覽器里面實現直接下載apk是不太可能的)

方法一:download屬性

首先看下面這種截圖:
下載按鈕

如果我們想實現點擊上面的下載按鈕下載一張圖片,你會如何實現?

我們可能會想到一個最簡單的方法,就是直接按鈕a標簽鏈接一張圖片,類似下面這樣:

<a href="large.jpg">下載</a>

但是,想法雖好,實際效果卻不是我們想要的,因為瀏覽器可以直接瀏覽圖片,因此,我們點擊下面的“下載”鏈接,並是不下載圖片,而是在新窗口直接瀏覽圖片。

我們希望點擊“下載”鏈接下載圖片而不是瀏覽,直接增加一個download屬性就可以:

<a href="large.jpg" download>下載</a>

不僅如此,我們還可以指定下載圖片的文件名:

<a href="index_logo.gif" download="_5332_.gif">下載</a>

如果后綴名一樣,我們還可以缺省,直接文件名:

<a href="index_logo.gif" download="_5332_">下載</a>

瀏覽器兼容性和跨域策略

如果需要下載的資源是跨域的,包括跨子域,在Chrome瀏覽器下,使用download屬性是可以下載的,但是,並不能重置下載的文件的命名;而FireFox瀏覽器下,則download屬性是無效的,也就是FireFox瀏覽器無論如何都不支持跨域

資源的download屬性下載。而,如果資源是同域名的,則兩個瀏覽器都是暢通無阻的下載,不會出現下載變瀏覽的情況。

是否支持download屬性的監測

要監測當前瀏覽器是否支持download屬性,一行JS代碼就可以了,如下:

var isSupportDownload = 'download' in document.createElement('a');

使用總結

1、在微信中無法使用download屬性

2、兼容性不好,在chrome上嘗試並沒有下載

方法二:window.location.href

window.location.href = 'http://imtt.dd.qq.com/16891/26747DD8B125A8479AD0C9D22CA47BC9.apk?fsname=com.snda.wifilocating_4.2.91_3211.apk&csr=1bbd';

點擊下載按鈕的時候改變location.href,拿在瀏覽器里面試了下,多個安卓機型都可以走通,但會出現空白頁,空白頁是因為改變href為apk的下載鏈接,網頁打開的時候會停留在一個空白頁,然后一般手機的狀態欄上會出現下載apk的進

度條。既然不想出現空白頁面的話,那不直接打開一個頁面而改成在當前頁打開就可以了。( 遇到的空白頁是因為有的手機下載的時候其實是跳轉到這個apk的地址,在那等着apk下載完成,這個等待的頁面就是個空白頁面了)

方法三:借助iframe

var src = 'http://imtt.dd.qq.com/16891/26747DD8B125A8479AD0C9D22CA47BC9.apk?fsname=com.snda.wifilocating_4.2.91_3211.apk&csr=1bbd';
var iframe = document.createElement('iframe');
iframe.style.display = 'none';
iframe.src = "javascript: '<script>location.href=\"" + src + "\"<\/script>'";
document.getElementsByTagName('body')[0].appendChild(iframe);

使用iframe的話,既可以實現下載,又可以不重新打開頁面,並且,對原頁面的布局不會產生任何影響。

方法四:借助form

var src = 'http://imtt.dd.qq.com/16891/26747DD8B125A8479AD0C9D22CA47BC9.apk?fsname=com.snda.wifilocating_4.2.91_3211.apk&csr=1bbd';
var form = document.createElement('form');
form.action = src;
document.getElementsByTagName('body')[0].appendChild(form);
form.submit();

既然使用iframe可以,那使用form一定也是可以的,form的action也可以發請求。

方法五:借助HTML5 Blob實現文本信息文件下載 【親測好用】

原理其實很簡單,我們可以將文本或者JS字符串信息借助Blob轉換成二進制,然后,作為<a>元素的href屬性,配合download屬性,實現下載。

代碼也比較簡單,如下示意(兼容Chrome和Firefox):

var funDownload = function (content, filename) {
    // 創建隱藏的可下載鏈接
    var eleLink = document.createElement('a');
    eleLink.download = filename;
    eleLink.style.display = 'none';
    // 字符內容轉變成blob地址
    var blob = new Blob([content]);
   // 簡單的理解一下就是將一個fileBlob類型的對象轉為UTF-16的字符串,並保存在當前操作的document eleLink.href
= URL.createObjectURL(blob); // 觸發點擊 document.body.appendChild(eleLink); eleLink.click(); // 然后移除 document.body.removeChild(eleLink); };

其中,content指需要下載的文本或字符串內容,filename指下載到系統中的文件名稱。

實例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script>
        window.onload = function() {
            var eleTextarea = document.querySelector('textarea');
            var eleButton = document.querySelector('input[type="button"]');

            // 下載文件方法
            var funDownload = function (content, filename) {
                var eleLink = document.createElement('a');
                eleLink.download = filename;
                eleLink.style.display = 'none';
                // 字符內容轉變成blob地址
                var blob = new Blob([content]);
                eleLink.href = URL.createObjectURL(blob);
                // 觸發點擊
                document.body.appendChild(eleLink);
                eleLink.click();
                // 然后移除
                document.body.removeChild(eleLink);
            };

            if ('download' in document.createElement('a')) {
                // 作為test.html文件下載
                eleButton.addEventListener('click', function () {
                    funDownload(eleTextarea.value, 'test.html');    
                });
            } else {
                eleButton.onclick = function () {
                    alert('瀏覽器不支持');    
                };
            }
        }
    </script>
</head>
<body>
        <textarea rows="11">
        </textarea>
        <p><input type="button" value="作為test.html文件下載"></p>
</body>
</html>

 點擊“下載”按鈕,會把文本域中的內容全部作為一個.html后綴文件下載下來,各流程效果如下面幾張圖:

觸發下載的JS代碼就幾行:

button.addEventListener('click', function () {
    funDownload(textarea.value, 'test.html');    
});

方法六:借助Base64實現任意文件下載

對於非文本文件,也是可以直接JS觸發下載的,例如,如果我們想下載一張圖片,可以把這張圖片轉換成base64格式,然后下載。

代碼示意:

var funDownload = function (domImg, filename) {
    // 創建隱藏的可下載鏈接
    var eleLink = document.createElement('a');
    eleLink.download = filename;
    eleLink.style.display = 'none';
    // 圖片轉base64地址
    var canvas = document.createElement('canvas');
    var context = canvas.getContext('2d');
    var width = domImg.naturalWidth;
    var height = domImg.naturalHeight;
    context.drawImage(domImg, 0, 0);
    // 如果是PNG圖片,則canvas.toDataURL('image/png')
    eleLink.href = canvas.toDataURL('image/jpeg');
    // 觸發點擊
    document.body.appendChild(eleLink);
    eleLink.click();
    // 然后移除
    document.body.removeChild(eleLink);
};

不止是.html文件,.txt.json等只要內容是文本的文件,都是可以利用這種小技巧實現下載的。

在Chrome瀏覽器,模擬點擊創建的<a>元素即使不append到頁面中,也是可以觸發下載的,但是在Firefox瀏覽器中卻不行,因此,上面的funDownload()方法有一個appendChildremoveChild的處理,就是為了兼容Firefox瀏覽器

總結

其實第二和第三種方法是擴展發揮了iframe和form的用法,單獨來看,我們知道iframe可以在父頁面里嵌套子頁面,知道form的action可以發請求或者跳轉頁面,這是很常見的功能,但是不知道它們會被用在下載文件這個需求上,且產生

的效果非常好。

有的類型的文件下載不了,方法二、三、四本質上都是改變location.href,當瀏覽器不能‘理解’這種類型時,就會直接下載,反之,瀏覽器就會直接打開,並不會下載

參考

H5頁面實現下載文件(apk、txt等)的三種方式

張鑫旭:JS前端創建html或json文件並瀏覽器導出下載

張鑫旭:了解HTML/HTML5中的download屬性

HTML5 進階系列:文件上傳下載(重點)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM