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

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

一、教程简介

FileReader API 是 HTML5 提供的异步文件读取接口,允许 Web 应用在客户端读取 File 或 Blob 对象的内容。FileReader 支持多种读取格式(文本、DataURL、ArrayBuffer、二进制字符串),并通过事件机制通知读取进度和结果。该 API 广泛应用于图片预览、文本文件查看、CSV/JSON 解析、文件哈希计算等场景,是客户端文件处理的核心工具。


二、核心概念

读取方式

方法 说明 结果格式
readAsText(file, encoding) 以文本方式读取 字符串
readAsDataURL(file) 以 Data URL 读取 base64 编码字符串
readAsArrayBuffer(file) 以 ArrayBuffer 读取 ArrayBuffer
readAsBinaryString(file) 以二进制字符串读取 二进制字符串(已废弃)

事件

事件 说明
onloadstart 读取开始
onprogress 读取进度更新
onload 读取成功完成
onerror 读取失败
onloadend 读取结束(无论成功或失败)
onabort 读取被中止

状态

状态 说明
EMPTY 0 尚未加载
LOADING 1 正在加载
DONE 2 加载完成

FileReader 与 FileReaderSync

特性 FileReader FileReaderSync
执行方式 异步 同步
使用环境 主线程 Worker 线程
事件机制 支持 不支持
阻塞 不阻塞 阻塞

三、语法与用法

基本读取

代码示例

const reader = new FileReader();

reader.onload = function(e) {
    console.log('读取结果:', e.target.result);
};

reader.onerror = function(e) {
    console.error('读取失败:', e.target.error);
};

// 读取为文本
reader.readAsText(file, 'UTF-8');

// 读取为 Data URL
reader.readAsDataURL(file);

// 读取为 ArrayBuffer
reader.readAsArrayBuffer(file);

进度监控

代码示例

reader.onprogress = function(e) {
    if (e.lengthComputable) {
        const percent = (e.loaded / e.total * 100).toFixed(1);
        console.log('进度:', percent + '%');
    }
};

中止读取

代码示例

reader.abort();

读取图片预览

代码示例

function previewImage(file) {
    const reader = new FileReader();
    reader.onload = function(e) {
        const img = document.createElement('img');
        img.src = e.target.result;
        document.body.appendChild(img);
    };
    reader.readAsDataURL(file);
}

读取文本文件

代码示例

function readTextFile(file) {
    const reader = new FileReader();
    reader.onload = function(e) {
        const text = e.target.result;
        console.log(text);
    };
    reader.readAsText(file, 'UTF-8');
}

四、代码示例

示例一:多功能文件阅读器

以下示例展示如何使用 FileReader 实现一个支持多种读取模式的文件阅读器:

代码示例

function readFile(file, mode) {
    const reader = new FileReader();

    reader.onprogress = function(e) {
        if (e.lengthComputable) {
            const percent = (e.loaded / e.total * 100).toFixed(1);
            console.log('读取进度:', percent + '%');
        }
    };

    reader.onload = function(e) {
        const result = e.target.result;
        if (mode === 'text') {
            console.log('文本内容:', result.substring(0, 1000));
        } else if (mode === 'dataurl') {
            console.log('Data URL 长度:', result.length);
        } else if (mode === 'arraybuffer') {
            const view = new Uint8Array(result);
            console.log('字节数:', view.length);
        }
    };

    reader.onerror = function() {
        console.error('读取失败:', reader.error.message);
    };

    switch (mode) {
        case 'text': reader.readAsText(file, 'UTF-8'); break;
        case 'dataurl': reader.readAsDataURL(file); break;
        case 'arraybuffer': reader.readAsArrayBuffer(file); break;
    }
}

示例二:CSV 文件解析

代码示例

function parseCSV(file) {
    const reader = new FileReader();
    reader.onload = function(e) {
        const text = e.target.result;
        const lines = text.split('\n');
        const headers = lines[0].split(',').map(h => h.trim());
        const rows = [];

        for (let i = 1; i < lines.length; i++) {
            const values = lines[i].split(',');
            const row = {};
            headers.forEach((h, idx) => {
                row[h] = (values[idx] || '').trim();
            });
            rows.push(row);
        }

        console.log('表头:', headers);
        console.log('数据行数:', rows.length);
        console.log('首行数据:', rows[0]);
    };
    reader.readAsText(file, 'UTF-8');
}

五、浏览器兼容性

浏览器 支持版本 备注
Chrome 6+ 完整支持
Firefox 3.6+ 完整支持
Safari 6+ 完整支持
Edge 12+ 完整支持
Opera 11.1+ 完整支持
IE 10+ 部分支持
iOS Safari 6+ 完整支持
Android 3+ 完整支持

六、注意事项与最佳实践

1. 内存管理

代码示例

// 大文件读取会占用大量内存
// DataURL 编码会增加约 33% 的体积
// 建议对大文件使用 slice 分片读取

// 不推荐:直接读取大文件为 DataURL
reader.readAsDataURL(largeFile); // 可能导致内存溢出

// 推荐:限制大小或分片处理
if (file.size > 5 * 1024 * 1024) {
    alert('文件过大,请选择小于 5MB 的文件');
} else {
    reader.readAsDataURL(file);
}

2. 错误处理

代码示例

const reader = new FileReader();

reader.onerror = function() {
    switch (reader.error.code) {
        case reader.error.NOT_FOUND_ERR:
            console.error('文件未找到');
            break;
        case reader.error.NOT_READABLE_ERR:
            console.error('文件不可读');
            break;
        case reader.error.SECURITY_ERR:
            console.error('安全限制');
            break;
        default:
            console.error('读取错误:', reader.error);
    }
};

3. 编码处理

代码示例

// 指定正确的编码
reader.readAsText(file, 'UTF-8');    // 默认 UTF-8
reader.readAsText(file, 'GBK');      // 中文 GBK
reader.readAsText(file, 'ISO-8859-1'); // 西文编码

// 检测编码(简单方法)
function detectEncoding(buffer) {
    const view = new Uint8Array(buffer);
    if (view[0] === 0xEF && view[1] === 0xBB && view[2] === 0xBF) return 'UTF-8';
    if (view[0] === 0xFF && view[1] === 0xFE) return 'UTF-16LE';
    if (view[0] === 0xFE && view[1] === 0xFF) return 'UTF-16BE';
    return 'UTF-8'; // 默认
}

4. 使用 URL.createObjectURL 替代 DataURL

代码示例

// 对于图片预览,URL.createObjectURL 更高效
// 不需要将整个文件读取为 base64

// 推荐
const url = URL.createObjectURL(file);
img.src = url;
img.onload = function() { URL.revokeObjectURL(url); };

// 不推荐(大文件时)
reader.onload = function(e) { img.src = e.target.result; };
reader.readAsDataURL(file);

七、代码规范示例

代码示例

// 推荐:封装 FileReader 工具
class FileReaderHelper {
    static readAsText(file, encoding = 'UTF-8') {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = () => resolve(reader.result);
            reader.onerror = () => reject(reader.error);
            reader.readAsText(file, encoding);
        });
    }

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

    static readAsArrayBuffer(file) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = () => resolve(reader.result);
            reader.onerror = () => reject(reader.error);
            reader.readAsArrayBuffer(file);
        });
    }

    static async readFileAsJSON(file) {
        const text = await this.readAsText(file);
        return JSON.parse(text);
    }

    static async computeFileHash(file, algorithm = 'SHA-256') {
        const buffer = await this.readAsArrayBuffer(file);
        const hashBuffer = await crypto.subtle.digest(algorithm, buffer);
        return Array.from(new Uint8Array(hashBuffer))
            .map(b => b.toString(16).padStart(2, '0'))
            .join('');
    }
}

// 使用示例
async function processFile(file) {
    try {
        const text = await FileReaderHelper.readAsText(file);
        console.log('文件内容:', text);

        const hash = await FileReaderHelper.computeFileHash(file);
        console.log('文件哈希:', hash);
    } catch (error) {
        console.error('文件读取失败:', error);
    }
}

八、常见问题与解决方案

常见问题

读取大文件时浏览器卡顿?

使用 file.slice() 分片读取,或使用 URL.createObjectURL 替代 readAsDataURL,避免一次性将大文件加载到内存中。

FileReader 只能同时读取一个文件?

每个 FileReader 实例同时只能读取一个文件,但可以创建多个 FileReader 实例并行读取多个文件,或使用 Promise.all 并发处理。

如何读取文件指定范围?

使用 file.slice(0, 1024) 截取部分内容,再用 FileReader 读取该 Blob 片段,适合大文件预览或哈希计算。

readAsBinaryString 已废弃怎么办?

使用 readAsArrayBuffer 替代,然后通过 new Uint8Array(buffer) 访问二进制数据。

九、总结

FileReader API 提供了在客户端异步读取文件内容的能力,支持文本、DataURL、ArrayBuffer 等多种格式,通过事件机制可以监控读取进度和处理错误。使用时需注意大文件的内存管理(分片读取或使用 URL.createObjectURL)、编码处理、错误处理和安全性。通过 Promise 封装可以简化异步操作,使代码更加清晰易用。FileReader 是实现图片预览、文本查看、CSV 解析等功能的核心工具。

标签: FileReader 文件读取 图片预览 CSV解析 File API HTML5

本文涉及AI创作

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

list快速访问

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

poll相关推荐