浏览器生成二维码,并转换成图片下载到本地

时间:2022-11-16 20:51:00

最近遇到在浏览器中生成二维码,并将二维码转换成图片下载到本地的需求

总的来说,有以下几个步骤

  1. 字符串转换成二维码
    这里可以使用插件 qrcode.js 生成,可以通过canvas (IE9+) 和table (IE8) 两种方式生成。

    $("#qrcode-container").empty().qrcode({ text: "http://www.baidu.com/" });
  2. Canvas转换成Base64,然后转换成Blob对象
    canvastoDataURL 方法可以将canvas转换成base64格式,再进一步生成Blob对象下载。因此在这一步,不支持Canvas的IE8就没办法生成base64了,而IE9也无法使用Blob对象,无法进行下一个步骤。

    var canvas = $("#qrcode-container").find("canvas")[0];
    var base64Text = canvas.toDataURL("image/png");
    var blob = getBlob(base64Text);
    function getBlob(base64) {
        var mimeString =  base64.split(',')[0].split(':')[1].split(';')[0]; // mime类型
        var byteString = atob(base64.split(',')[1]); //base64 解码
        var arrayBuffer = new ArrayBuffer(byteString.length); //创建缓冲数组
        var intArray = new Uint8Array(arrayBuffer); //创建视图
        for (i = 0; i < byteString.length; i += 1) {
             intArray[i] = byteString.charCodeAt(i);
        }
        return new Blob([intArray], { type:  mimeString });
    }
  3. 使用URL.createObjectURL() 方法生成 DOMString,绑定到a 标签的 href 属性中,利用 a 标签的 download 属性进行下载

    引用MDN的解释:

    URL.createObjectURL() 静态方法会创建一个 DOMString,其中包含一个表示参数中给出的对象的URL。这个 URL 的生命周期和创建它的窗口中的 document 绑定。这个新的URL 对象表示指定的 File 对象或 Blob 对象。

    download属性的解释MDN

    此属性指示浏览器下载URL而不是导航到URL,因此将提示用户将其保存为本地文件。
    如果属性有一个值,它将在保存提示中用作预先填写的文件名 (用户仍然可以根据需要更改文件名)。对允许的值没有限制,但是/和\被转换为下划线。大多数文件系统限制文件名中的一些标点符号,浏览器会相应地调整建议的名称。

    绑定到a标签的href后,使用click触发点击事件即可下载。注意IE、FireFox的使用的区别。

    var downloadFile = function(blob, fileName) {
        if(navigator.msSaveBlob) {
            // IE的Blob保存方法
            navigator.msSaveBlob(blob, fileName); 
        } else {
            var link = document.createElement('a');
            var href = window.URL.createObjectURL(blob);
            link.href = href;
            link.download = fileName;
            document.body.appendChild(link); // firefox需要把a添加到dom才能正确执行click
            link.click();
    
            // 延时保证下载成功执行,否则可能下载未找到文件的问题
            setTimeout(function() {
                window.URL.revokeObjectURL(href); // 释放Url对象
                document.body.removeChild(link);
            }, 100);
        }
    };

    关于URL.revokeObjectURL方法

    在每次调用 createObjectURL() 方法时,都会创建一个新的 URL 对象,即使你已经用相同的对象作为参数创建过。当不再需要这些 URL 对象时,每个对象必须通过调用 URL.revokeObjectURL() 方法来释放。浏览器会在文档退出的时候自动释放它们,但是为了获得最佳性能和内存使用状况,你应该在安全的时机主动释放掉它们。