zoukankan      html  css  js  c++  java
  • 任意内容转base64及Data URL

    Blob对象和File对象

    Blob对象是不可变的原始数据, 可以读取为文本或二进制数据.
    File 对象是特殊类型的 Blob,且可以用在任意的 Blob 类型的 context 中。比如说, FileReader, URL.createObjectURL(), createImageBitmap(), 及 XMLHttpRequest.send() 都能处理 Blob 和 File。

    new Blob([text1, text2], { type: 'application/octet-stream' });
    new File([file], 'rename.mp4'); // 复制文件并临时重命名
    

    代码

    /**
     * 演示使用a标签生成下载, 命名下载文件名, 数据转base64
     * Data URLs 由四个部分组成:前缀(data:)、指示数据类型的MIME类型、如果非文本则为可选的base64标记、数据本身:
     * data:[<mediatype>][;base64],<data>
     */
    import { Component } from 'react';
    import Button from '@/components/Button';
    import Code from '@/components/Code';
    
    class Demo extends Component {
        handleClick(event) {
            let a = document.createElement('a');
            let text = 'ABC你好'; // 要存放的utf-8文本, 无法使用btoa转base64编码
            switch (event.target.innerText) {
                case '使用URI编码文本后再base64编码的Data URLs': {
                    a.href = `data: application/octet-stream; base64,${btoa(encodeURI(text))}`; // 文本中含有汉字而无法使用btoa转义, 因此使用URI编码文本
                    break;
                }
                case '使用utf-8编码文本的Data URLs': {
                    a.href = `data: application/octet-stream; utf-8,${text}`; // 不使用base64, 使用utf-8编码保存文件
                    break;
                }
                /* 在每次调用 createObjectURL() 方法时,都会创建一个新的 URL 对象,即使你已经用相同的对象作为参数创建过。
                 * 当不再需要这些 URL 对象时,每个对象必须通过调用 URL.revokeObjectURL() 方法来释放。
                 */
                case '使用Blob创建ObjectURL本地链接': {
                    let blob = new Blob([text, 123], { type: 'application/octet-stream' });
                    console.log(blob); // Blob { size: 12, type: "application/octet-stream" }
                    a.href = URL.createObjectURL(blob);
                    console.log(a.href); // 一个以"blob:"开头的URL地址
                    break;
                }
                case '使用FileReader将Blob编码为Data URLs': {
                    let reader = new FileReader();
                    reader.addEventListener('loadend', event => {
                        a.href = event.target.result;
                        console.log(a.href); // Data URLs
                        // 这里是异步的, 所以要重复操作
                        a.download = '文件.end'; // 8位位组八位字节流可以自定义文件后缀
                        a.click(); // 遗憾的是, 无法感知文件下载完成事件, 从而无法主动释放Blob对象创建的ObjectURL
                    });
                    let blob = new Blob([text], { type: 'application/octet-stream' });
                    reader.readAsDataURL(blob);
                    break;
                }
            }
            a.download = '文件.end'; // 8位位组八位字节流可以自定义文件后缀
            a.click(); // 遗憾的是, 无法感知文件下载完成事件, 从而无法主动释放Blob对象创建的ObjectURL
        }
        render() {
            return (
                <div>
                    <Button onClick={_ => this.handleClick(_)}>使用URI编码文本后再base64编码的Data URLs</Button>
                    <Button onClick={_ => this.handleClick(_)}>使用utf-8编码文本的Data URLs</Button>
                    <Button onClick={_ => this.handleClick(_)}>使用Blob创建ObjectURL本地链接</Button>
                    <Button onClick={_ => this.handleClick(_)}>使用FileReader将Blob编码为Data URLs</Button>
                </div>
            );
        }
    }
    
    export default (
        <div>
            <Demo />
            <Code>{require('!raw-loader!.').default}</Code>
        </div>
    );
    

    前端

    缺陷:函数参数有限,所以大数据会抛出错误RangeError: Maximum call stack size exceeded。

    function String2ArrayBuffer(str, callback) {
        var b = new Blob([str]);
        var f = new FileReader();
        f.onload = function (e) {
            callback(e.target.result);
        }
        f.readAsArrayBuffer(b);
    }
    
    String2ArrayBuffer('你好abc', function (buf) {
        const base64String = window.btoa(String.fromCharCode(...new Uint8Array(buf)));
        console.log(base64String);
    });
    

    修复:

    function String2ArrayBuffer(str, callback) {
        var b = new Blob([str]);
        var f = new FileReader();
        f.onload = function (e) {
            callback(e.target.result);
        }
        f.readAsArrayBuffer(b);
    }
    
    function arrayBufferToBase64(buffer) {
        var binary = '';
        var bytes = new Uint8Array(buffer);
        var len = bytes.byteLength;
        for (var i = 0; i < len; i++) {
            binary += String.fromCharCode(bytes[i]);
        }
        return window.btoa(binary);
    }
    
    String2ArrayBuffer('你好abc', function (buf) {
        const base64String = arrayBufferToBase64(buf);
        console.log(base64String);
    });
    

    Node.js

  • 相关阅读:
    【转帖】如何学好 C 语言
    设计模式:单件模式(Singleton Pattern)
    如果软件正在占领全世界.为什么程序员得不到任何尊重?
    【转】程序员技术练级攻略
    JS闭包理解的彻底吗?
    设计模式:原型模式(Prototype Pattern)
    关于基础类型
    IIS5和IIS6的Asp.net应用程序生命周期事件和Global.asax文件
    App_Code文件夹和Bin文件夹
    构造函数
  • 原文地址:https://www.cnblogs.com/develon/p/13748986.html
Copyright © 2011-2022 走看看