pin_drop当前位置:知识文库 ❯ 图文

HTML5 API:HTML5 Blob API - 完整教程与代码示例

一、教程简介

Blob(Binary Large Object)API 是 HTML5 提供的用于处理二进制数据的接口,代表一个不可变的原始数据块。Blob 可以包含任意类型的数据(文本、图片、音视频等),是 File API 的基础,也是处理二进制数据的核心工具。Blob 广泛应用于文件下载、图片处理、数据导出、流式处理等场景。

二、核心概念

Blob 与 File 的关系

代码示例

Blob(原始二进制数据)
  ├── 属性:size, type
  ├── 方法:slice(), stream(), text(), arrayBuffer()
  └── File(继承 Blob)
       ├── 额外属性:name, lastModified
       └── 通过 <input> 或拖放获取

Blob 构造函数

代码示例

const blob = new Blob(blobParts, options);
参数 说明
blobParts 数组,包含 ArrayBuffer、Blob、String 等
options.type MIME 类型
options.endings 换行符处理:transparent/native

代码示例

// 从字符串创建
const textBlob = new Blob(['Hello, World!'], { type: 'text/plain' });

// 从 JSON 创建
const jsonBlob = new Blob([JSON.stringify({ name: '张三' })], { type: 'application/json' });

// 从 HTML 创建
const htmlBlob = new Blob(['<h1>Hello</h1>'], { type: 'text/html' });

// 合并多个 Blob
const combined = new Blob([blob1, blob2, 'extra text'], { type: 'text/plain' });

Blob 属性与方法

属性/方法 说明
size 数据大小(字节)
type MIME 类型
slice(start, end, type) 截取部分数据
stream() 返回 ReadableStream
text() 读取为文本(Promise)
arrayBuffer() 读取为 ArrayBuffer(Promise)

URL.createObjectURL

代码示例

const url = URL.createObjectURL(blob);  // 创建临时 URL
// 使用 URL...
URL.revokeObjectURL(url);  // 释放内存

三、语法与用法

文件下载

代码示例

function downloadFile(content, filename, type) {
    const blob = new Blob([content], { type });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = filename;
    a.click();
    URL.revokeObjectURL(url);
}

downloadFile('Hello, World!', 'hello.txt', 'text/plain');
downloadFile(JSON.stringify(data), 'data.json', 'application/json');

Blob 读取

代码示例

const blob = new Blob(['Hello'], { type: 'text/plain' });

// 读取为文本
const text = await blob.text();

// 读取为 ArrayBuffer
const buffer = await blob.arrayBuffer();

// 流式读取
const stream = blob.stream();
const reader = stream.getReader();

四、代码示例

示例一:文件生成与下载

代码示例

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Blob API - 文件生成与下载</title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
            background: #f5f7fa;
            min-height: 100vh;
            padding: 30px 20px;
        }
        .container { max-width: 640px; margin: 0 auto; }
        h1 { font-size: 24px; color: #2d3436; margin-bottom: 8px; }
        .desc { color: #636e72; font-size: 14px; margin-bottom: 24px; }
        .card {
            background: #fff;
            border-radius: 12px;
            padding: 24px;
            margin-bottom: 16px;
            box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
        }
        .card h2 { font-size: 16px; color: #2d3436; margin-bottom: 16px; }
        textarea {
            width: 100%;
            padding: 12px;
            border: 1px solid #ddd;
            border-radius: 8px;
            font-size: 14px;
            min-height: 120px;
            resize: vertical;
            outline: none;
            font-family: inherit;
        }
        textarea:focus { border-color: #0984e3; }
        .btn-group { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 12px; }
        button {
            padding: 8px 18px;
            border: none;
            border-radius: 8px;
            font-size: 13px;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.2s;
        }
        .btn-blue { background: #0984e3; color: #fff; }
        .btn-blue:hover { background: #0770c2; }
        .btn-green { background: #00b894; color: #fff; }
        .btn-green:hover { background: #00a381; }
        .btn-orange { background: #fdcb6e; color: #333; }
        .btn-orange:hover { background: #e5b85c; }
        .btn-purple { background: #a29bfe; color: #fff; }
        .btn-purple:hover { background: #8c82f7; }
        .preview-area {
            background: #f8f9fa;
            border-radius: 8px;
            padding: 16px;
            margin-top: 12px;
            min-height: 60px;
            font-size: 13px;
            color: #333;
        }
        .preview-img {
            max-width: 100%;
            max-height: 200px;
            border-radius: 8px;
        }
        .blob-info {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 12px;
            margin-top: 12px;
        }
        .info-item {
            background: #f8f9fa;
            border-radius: 8px;
            padding: 12px;
            text-align: center;
        }
        .info-label { font-size: 11px; color: #999; margin-bottom: 4px; }
        .info-value { font-size: 16px; font-weight: 700; color: #0984e3; }
    </style>
</head>
<body>
    <div class="container">
        <h1>Blob 文件生成与下载</h1>
        <p class="desc">使用 Blob API 生成不同类型的文件并下载。</p>

        <div class="card">
            <h2>文本文件</h2>
            <textarea id="textContent">这是一个使用 Blob API 生成的文本文件。
可以包含多行文本内容。
支持中文和各种特殊字符!@#$%</textarea>
            <div class="btn-group">
                <button class="btn-blue" onclick="downloadText()">下载 TXT</button>
                <button class="btn-green" onclick="downloadCSV()">下载 CSV</button>
                <button class="btn-orange" onclick="downloadJSON()">下载 JSON</button>
                <button class="btn-purple" onclick="downloadHTML()">下载 HTML</button>
            </div>
        </div>

        <div class="card">
            <h2>Canvas 图片导出</h2>
            <canvas id="drawCanvas" width="400" height="200" style="width:100%;border:1px solid #eee;border-radius:8px;"></canvas>
            <div class="btn-group">
                <button class="btn-blue" onclick="downloadCanvasPNG()">下载 PNG</button>
                <button class="btn-green" onclick="downloadCanvasJPG()">下载 JPG</button>
                <button class="btn-orange" onclick="previewCanvas()">预览</button>
            </div>
            <div id="canvasPreview"></div>
        </div>

        <div class="card">
            <h2>Blob 信息</h2>
            <div class="blob-info" id="blobInfo">
                <div class="info-item">
                    <div class="info-label">大小</div>
                    <div class="info-value" id="blobSize">--</div>
                </div>
                <div class="info-item">
                    <div class="info-label">类型</div>
                    <div class="info-value" id="blobType">--</div>
                </div>
            </div>
        </div>
    </div>

    <script>
        // 初始化 Canvas
        const canvas = document.getElementById('drawCanvas');
        const ctx = canvas.getContext('2d');

        function drawCanvas() {
            const w = canvas.width, h = canvas.height;
            const gradient = ctx.createLinearGradient(0, 0, w, h);
            gradient.addColorStop(0, '#667eea');
            gradient.addColorStop(1, '#764ba2');
            ctx.fillStyle = gradient;
            ctx.fillRect(0, 0, w, h);

            ctx.fillStyle = '#fff';
            ctx.font = 'bold 28px sans-serif';
            ctx.textAlign = 'center';
            ctx.fillText('Blob Canvas 导出', w / 2, h / 2 - 10);
            ctx.font = '14px sans-serif';
            ctx.fillText('点击按钮导出为图片', w / 2, h / 2 + 20);
        }
        drawCanvas();

        function updateBlobInfo(blob) {
            document.getElementById('blobSize').textContent = formatSize(blob.size);
            document.getElementById('blobType').textContent = blob.type || '未知';
        }

        function downloadBlob(blob, filename) {
            updateBlobInfo(blob);
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = filename;
            a.click();
            URL.revokeObjectURL(url);
        }

        function downloadText() {
            const text = document.getElementById('textContent').value;
            const blob = new Blob([text], { type: 'text/plain;charset=utf-8' });
            downloadBlob(blob, 'hello.txt');
        }

        function downloadCSV() {
            const data = [
                ['姓名', '年龄', '城市'],
                ['张三', '25', '北京'],
                ['李四', '30', '上海'],
                ['王五', '28', '广州']
            ];
            const csv = data.map(row => row.join(',')).join('\n');
            const blob = new Blob(['\uFEFF' + csv], { type: 'text/csv;charset=utf-8' });
            downloadBlob(blob, 'data.csv');
        }

        function downloadJSON() {
            const data = {
                title: 'Blob 示例数据',
                items: [
                    { id: 1, name: '项目一', status: '完成' },
                    { id: 2, name: '项目二', status: '进行中' },
                    { id: 3, name: '项目三', status: '待开始' }
                ],
                generated: new Date().toISOString()
            };
            const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
            downloadBlob(blob, 'data.json');
        }

        function downloadHTML() {
            const html = '<!DOCTYPE html>\n<html lang="zh-CN">\n<head>\n<meta charset="UTF-8">\n<title>Blob 生成的 HTML</title>\n<style>body{font-family:sans-serif;display:flex;justify-content:center;align-items:center;min-height:100vh;background:#667eea;color:#fff;}</style>\n</head>\n<body>\n<h1>由 Blob API 生成的 HTML 文件</h1>\n</body>\n</html>';
            const blob = new Blob([html], { type: 'text/html;charset=utf-8' });
            downloadBlob(blob, 'page.html');
        }

        function downloadCanvasPNG() {
            canvas.toBlob(function (blob) {
                downloadBlob(blob, 'canvas.png');
            }, 'image/png');
        }

        function downloadCanvasJPG() {
            canvas.toBlob(function (blob) {
                downloadBlob(blob, 'canvas.jpg');
            }, 'image/jpeg', 0.9);
        }

        function previewCanvas() {
            canvas.toBlob(function (blob) {
                updateBlobInfo(blob);
                const url = URL.createObjectURL(blob);
                const preview = document.getElementById('canvasPreview');
                preview.innerHTML = '<img src="' + url + '" class="preview-img" alt="预览" style="margin-top:12px;">';
            }, 'image/png');
        }

        function formatSize(bytes) {
            if (bytes === 0) return '0 B';
            const k = 1024;
            const sizes = ['B', 'KB', 'MB', 'GB'];
            const i = Math.floor(Math.log(bytes) / Math.log(k));
            return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
        }
    </script>
</body>
</html>

五、浏览器兼容性

浏览器 Blob URL.createObjectURL Blob.stream()
Chrome 20+ 23+ 70+
Firefox 13+ 4+ 69+
Safari 8+ 6+ 14.1+
Edge 12+ 12+ 79+
IE 10+ 10+ 不支持

六、注意事项与最佳实践

1. 及时释放 ObjectURL

代码示例

const url = URL.createObjectURL(blob);
// 使用完毕后释放
URL.revokeObjectURL(url);
// 否则会造成内存泄漏

2. 大文件处理

代码示例

// 使用 stream() 流式处理大 Blob
const stream = blob.stream();
const reader = stream.getReader();

while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    // 处理 value(Uint8Array)
}

3. Blob 合并

代码示例

// 合并多个 Blob
const merged = new Blob([blob1, blob2, new Uint8Array([1, 2, 3])], {
    type: 'application/octet-stream'
});

七、代码规范示例

代码示例

class BlobHelper {
    static create(content, type = 'text/plain') {
        return new Blob([content], { type });
    }

    static async toDataURL(blob) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = () => resolve(reader.result);
            reader.onerror = reject;
            reader.readAsDataURL(blob);
        });
    }

    static async toArrayBuffer(blob) {
        return blob.arrayBuffer();
    }

    static async toText(blob) {
        return blob.text();
    }

    static download(blob, filename) {
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = filename;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
        URL.revokeObjectURL(url);
    }

    static slice(blob, start, end, type) {
        return blob.slice(start, end, type);
    }

    static merge(blobs, type = 'application/octet-stream') {
        return new Blob(blobs, { type });
    }
}

八、常见问题与解决方案

常见问题

Q1:Blob URL 在新标签页打开后失效?

解答:Blob URL 只在创建它的文档生命周期内有效。刷新页面后 URL 失效。

Q2:如何将 Base64 转为 Blob?

解决方案:使用 atob 解码 Base64 字符串,然后创建 Uint8Array 并转为 Blob。

代码示例

function base64ToBlob(base64, type = 'image/png') {
    const binary = atob(base64.split(',')[1] || base64);
    const bytes = new Uint8Array(binary.length);
    for (let i = 0; i < binary.length; i++) {
        bytes[i] = binary.charCodeAt(i);
    }
    return new Blob([bytes], { type });
}
Q3:如何计算 Blob 的哈希值?

解决方案:使用 crypto.subtle.digest 计算哈希值。

代码示例

async function hashBlob(blob) {
    const buffer = await blob.arrayBuffer();
    const hash = await crypto.subtle.digest('SHA-256', buffer);
    return Array.from(new Uint8Array(hash))
        .map(b => b.toString(16).padStart(2, '0'))
        .join('');
}

九、总结

Blob API 是处理二进制数据的核心工具,可以创建、合并、切片和读取二进制数据。配合 URL.createObjectURL 可以实现文件下载和预览,配合 FileReader 可以读取 Blob 内容,配合 Canvas 可以导出图片。使用时需注意及时释放 ObjectURL 防止内存泄漏,大文件使用 stream() 流式处理,以及正确设置 MIME 类型。

标签: Blob API 二进制数据 文件下载 ObjectURL File API

本文涉及AI创作

内容由AI创作,请仔细甄别

list快速访问

上一篇: HTML5 API:HTML5 Fetch API - 完整教程与代码示例 下一篇: HTML5 API:HTML5 URL API - 完整教程与代码示例

poll相关推荐