File和Blob对象详解

1. 基本概念

1.1 Blob对象

Blob(Binary Large Object)是表示二进制数据的对象,是JavaScript中处理二进制数据的基础类型。1 5

定义

  • Blob对象表示一个不可变、原始数据的类文件对象
  • 它的数据可以按文本或二进制的格式进行读取
  • 也可以转换成ReadableStream来用于数据操作

构造方法

new Blob(blobParts, options);

参数

  • blobParts:数组类型,可以存放任意个ArrayBuffer、ArrayBufferView、Blob或DOMString(会编码为utf-8)
  • options:可选,可以设置blob的type和endings

1.2 File对象

File对象是特殊类型的Blob,继承了Blob的功能并扩展了与文件系统相关的功能。3 2

定义

  • File接口提供有关文件的信息,并允许网页中的JavaScript访问其内容
  • File是Blob的子类,继承了Blob的所有属性和方法

获取File对象的方式

  • 通过<input type="file">元素的files属性
  • 通过拖放操作的DataTransfer.files属性
  • 通过构造函数new File()

2. Blob与File的区别与联系

2.1 联系

  • File是Blob的子类,继承了Blob的所有属性和方法 3
  • 两者都可以用于处理二进制数据
  • 都支持slice方法来获取数据的子集

2.2 区别

特性BlobFile
元数据不包含文件元数据包含文件名、修改日期等元数据
用途通用二进制数据处理专注于文件系统交互
创建方式通过构造函数或Canvas等API通常从用户输入或拖放获取
属性size, typename, lastModified, size, type

3. Blob对象详解

3.1 属性

  • size:Blob对象中所包含数据的大小(字节)
  • type:Blob对象所包含数据的MIME类型,如果类型未知,则为空字符串

3.2 方法

  • slice([start[, end[, contentType]]]):返回一个新的Blob对象,包含了源Blob对象中指定范围内的数据
  • stream():返回一个ReadableStream,读取Blob内容
  • text():返回一个Promise,完成后得到Blob内容的UTF-8格式字符串
  • arrayBuffer():返回一个Promise,完成后得到一个ArrayBuffer表示的Blob数据

3.3 常见用途

  • 生成和处理二进制数据
  • 创建URL(通过URL.createObjectURL)
  • 文件下载
  • 图像处理
  • 音视频处理

4. File对象详解

4.1 属性

  • name:文件名,不包含路径
  • size:文件大小(字节)
  • type:文件的MIME类型
  • lastModified:文件最后修改时间的时间戳(毫秒) 1

4.2 方法

File对象继承了Blob的所有方法,包括:

  • slice()
  • stream()
  • text()
  • arrayBuffer()

4.3 FileReader API

FileReader是一个用于读取File或Blob内容的API:

const reader = new FileReader();
 
// 读取完成事件
reader.onload = function(e) {
    const content = e.target.result;
    // 处理文件内容
};
 
// 读取文件
reader.readAsText(file); // 读取为文本
// 或
reader.readAsDataURL(file); // 读取为Data URL
// 或
reader.readAsArrayBuffer(file); // 读取为ArrayBuffer

5. 实际应用场景

5.1 文件上传

// 获取文件输入元素
const fileInput = document.querySelector('#fileInput');
 
// 监听change事件
fileInput.addEventListener('change', function(e) {
    // 获取选择的文件列表
    const files = e.target.files;
    
    // 创建FormData对象
    const formData = new FormData();
    
    // 添加文件到FormData
    for (let i = 0; i < files.length; i++) {
        formData.append('file' + i, files[i]);
    }
    
    // 使用fetch API上传
    fetch('/upload', {
        method: 'POST',
        body: formData
    })
    .then(response => response.json())
    .then(data => console.log('上传成功:', data))
    .catch(error => console.error('上传失败:', error));
});

5.2 图片预览

function previewImage(file) {
    // 确保文件是图片
    if (!file.type.match('image.*')) {
        return;
    }
    
    const reader = new FileReader();
    
    // 设置读取完成事件
    reader.onload = function(e) {
        const img = document.createElement('img');
        img.src = e.target.result;
        document.getElementById('preview').appendChild(img);
    };
    
    // 读取文件为Data URL
    reader.readAsDataURL(file);
}
 
// 使用示例
document.querySelector('#imageInput').addEventListener('change', function(e) {
    const files = e.target.files;
    for (let i = 0; i < files.length; i++) {
        previewImage(files[i]);
    }
});

5.3 文件下载

function downloadFile(content, filename, contentType) {
    // 创建Blob对象
    const blob = new Blob([content], { type: contentType });
    
    // 创建URL
    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);
}
 
// 使用示例 - 下载JSON数据
const data = { name: 'example', value: 42 };
documentFile(JSON.stringify(data), 'data.json', 'application/json');
 
// 使用示例 - 下载文本
documentFile('Hello, World!', 'hello.txt', 'text/plain');

5.4 从URL创建Blob

async function fetchImageAsBlob(url) {
    const response = await fetch(url);
    const blob = await response.blob();
    return blob;
}
 
// 使用示例
fetchImageAsBlob('https://example.com/image.jpg')
    .then(blob => {
        const img = document.createElement('img');
        img.src = URL.createObjectURL(blob);
        document.body.appendChild(img);
    })
    .catch(error => console.error('获取图片失败:', error));

5.5 Canvas转换为Blob

const canvas = document.querySelector('canvas');
 
canvas.toBlob(function(blob) {
    // 使用生成的Blob
    const url = URL.createObjectURL(blob);
    const img = document.createElement('img');
    img.src = url;
    document.body.appendChild(img);
}, 'image/jpeg', 0.95); // JPEG格式,95%质量

6. 兼容性与注意事项

  • Blob和File API在现代浏览器中得到了广泛支持
  • 在处理大文件时,应考虑使用分片上传
  • 使用完URL.createObjectURL()创建的URL后,应调用URL.revokeObjectURL()释放内存
  • 在移动设备上处理大型Blob可能会导致性能问题
  • 对于旧版浏览器,可能需要使用polyfill

7. 总结

Blob和File对象是Web前端处理二进制数据的强大工具:

  • Blob是通用的二进制数据容器,适用于各种二进制数据处理场景
  • File是Blob的特化版本,专注于文件操作,提供了额外的文件元数据
  • 两者结合使用,可以实现文件上传、下载、预览等常见功能
  • 通过FileReader、URL.createObjectURL等API,可以方便地读取和操作这些对象

在前端开发中,熟练掌握Blob和File对象的使用,对于处理用户上传、文件生成、媒体处理等场景至关重要。