zoukankan      html  css  js  c++  java
  • 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 进阶系列:文件上传下载(重点)

  • 相关阅读:
    数据结构作业-二叉树
    51nod 1163 最高的奖励
    51nod 1091 线段的重叠
    实验1 顺序表及其应用
    51nod 1459 迷宫游戏 dijkstra模板
    html5拖拽
    onbeforeunload、onpagehide、onunload、onload、onpageshow的正确执行顺序
    HTML5游戏2D开发引擎
    如何定义现代浏览器
    api文档设计工具:RAML、Swagger
  • 原文地址:https://www.cnblogs.com/kunmomo/p/12917900.html
Copyright © 2011-2022 走看看