任意內容轉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


免責聲明!

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



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