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

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

一、教程简介

File API 是 HTML5 提供的一组用于在客户端处理文件信息的接口,允许 Web 应用读取文件的元数据(名称、大小、类型、修改时间等),而无需将文件上传到服务器。File API 通常与 <input type="file"> 元素和拖放(Drag and Drop)API 配合使用,是构建文件上传、文件预览等功能的底层基础。


二、核心概念

File 对象

File 对象继承自 Blob,包含文件的元数据信息:

属性 说明 示例
name 文件名 "photo.jpg"
size 文件大小(字节) 1048576
type MIME 类型 "image/jpeg"
lastModified 最后修改时间戳 1700000000000
lastModifiedDate 最后修改时间(Date 对象) Date

获取 File 对象的方式

  • 通过 <input> 元素input.files 返回 FileList

  • 通过拖放dataTransfer.files 返回 FileList

  • 通过 File 构造函数new File(bits, name, options)

FileList 与 File

代码示例

// FileList 是类数组对象
const fileList = input.files;

fileList.length;          // 文件数量
fileList[0];              // 第一个 File 对象
fileList.item(0);         // 同上

// 遍历
for (let i = 0; i < fileList.length; i++) {
    const file = fileList[i];
    console.log(file.name, file.size, file.type);
}

Blob 与 File 的关系

代码示例

Blob(原始二进制数据)
  └── File(Blob + 文件元数据)
       ├── name
       ├── lastModified
       └── 继承 Blob 的方法
            ├── slice()
            ├── stream()
            ├── text()
            └── arrayBuffer()

三、语法与用法

通过 input 获取文件

代码示例

<input type="file" id="fileInput" multiple>

代码示例

const input = document.getElementById('fileInput');

input.addEventListener('change', function(e) {
    const files = e.target.files;
    for (const file of files) {
        console.log('文件名:', file.name);
        console.log('大小:', file.size, '字节');
        console.log('类型:', file.type);
        console.log('修改时间:', new Date(file.lastModified));
    }
});

通过拖放获取文件

代码示例

dropZone.addEventListener('drop', function(e) {
    e.preventDefault();
    const files = e.dataTransfer.files;
    // 处理文件...
});

File 构造函数

代码示例

const file = new File(['Hello, World!'], 'hello.txt', {
    type: 'text/plain',
    lastModified: Date.now()
});

Blob 的 slice 方法

代码示例

// 分片读取大文件
const chunk = file.slice(start, end, contentType);

accept 属性限制文件类型

代码示例

<!-- 只接受图片 -->
<input type="file" accept="image/*">

<!-- 只接受 PDF -->
<input type="file" accept=".pdf,application/pdf">

<!-- 接受图片和 PDF -->
<input type="file" accept="image/*,.pdf">

<!-- 多选 -->
<input type="file" multiple accept="image/*">

四、代码示例

示例一:文件信息查看器

以下示例展示如何使用 File API 获取文件元数据并展示:

代码示例

// 获取文件信息
function handleFiles(files) {
    const fileArray = Array.from(files);
    
    // 汇总信息
    const totalCount = fileArray.length;
    const totalSize = fileArray.reduce((s, f) => s + f.size, 0);
    
    // 遍历文件
    fileArray.forEach(function(file) {
        console.log('文件名:', file.name);
        console.log('大小:', formatSize(file.size));
        console.log('类型:', file.type || '未知');
        console.log('修改时间:', new Date(file.lastModified));
    });
}

// 格式化文件大小
function formatSize(bytes) {
    if (bytes === 0) return '0 B';
    const k = 1024;
    const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}

示例二:文件分片上传模拟

代码示例

const CHUNK_SIZE = 1024 * 1024; // 1MB

async function uploadFile(file) {
    const totalChunks = Math.ceil(file.size / CHUNK_SIZE);
    
    for (let i = 0; i < totalChunks; i++) {
        const start = i * CHUNK_SIZE;
        const end = Math.min(start + CHUNK_SIZE, file.size);
        const chunk = file.slice(start, end);
        
        // 上传分片
        await uploadChunk(chunk, i);
        
        // 更新进度
        const percent = Math.round((i + 1) / totalChunks * 100);
        console.log('上传进度:', percent + '%');
    }
}

async function uploadChunk(chunk, index) {
    // 模拟上传
    await new Promise(resolve => setTimeout(resolve, 300));
    console.log('分片', index + 1, '上传完成');
}

五、浏览器兼容性

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

六、注意事项与最佳实践

1. 文件大小验证

代码示例

input.addEventListener('change', function(e) {
    const MAX_SIZE = 10 * 1024 * 1024; // 10MB
    for (const file of e.target.files) {
        if (file.size > MAX_SIZE) {
            alert(file.name + ' 超过 10MB 限制');
            return;
        }
    }
});

2. 文件类型验证

代码示例

function validateFileType(file, allowedTypes) {
    return allowedTypes.some(type => {
        if (type.endsWith('/*')) {
            return file.type.startsWith(type.replace('/*', '/'));
        }
        return file.type === type || file.name.endsWith(type);
    });
}

// 使用
const allowed = ['image/*', '.pdf', 'text/plain'];
if (!validateFileType(file, allowed)) {
    alert('不支持的文件类型');
}

3. 安全注意事项

  • 不要信任客户端验证:服务端必须再次验证文件类型和大小

  • 注意文件名安全:文件名可能包含特殊字符或路径遍历攻击

  • 限制文件数量:防止用户选择过多文件

4. 大文件处理

代码示例

// 使用 slice 分片处理大文件
function processLargeFile(file, chunkSize = 1024 * 1024) {
    const totalChunks = Math.ceil(file.size / chunkSize);
    let currentChunk = 0;

    function processNext() {
        if (currentChunk >= totalChunks) {
            console.log('处理完成');
            return;
        }

        const start = currentChunk * chunkSize;
        const end = Math.min(start + chunkSize, file.size);
        const chunk = file.slice(start, end);

        // 处理当前分片
        processChunk(chunk, currentChunk).then(() => {
            currentChunk++;
            processNext();
        });
    }

    processNext();
}

七、代码规范示例

代码示例

// 推荐:封装文件工具类
class FileUtils {
    // 格式化文件大小
    static formatSize(bytes) {
        if (bytes === 0) return '0 B';
        const k = 1024;
        const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
        const i = Math.floor(Math.log(bytes) / Math.log(k));
        return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
    }

    // 获取文件扩展名
    static getExtension(filename) {
        const parts = filename.split('.');
        return parts.length > 1 ? parts.pop().toLowerCase() : '';
    }

    // 验证文件类型
    static isType(file, types) {
        return types.some(type => {
            if (type.endsWith('/*')) {
                return file.type.startsWith(type.slice(0, -1));
            }
            if (type.startsWith('.')) {
                return FileUtils.getExtension(file.name) === type.slice(1);
            }
            return file.type === type;
        });
    }

    // 验证文件大小
    static isWithinSize(file, maxSize) {
        return file.size <= maxSize;
    }
}

// 使用示例
input.addEventListener('change', function(e) {
    const file = e.target.files[0];
    if (!FileUtils.isType(file, ['image/*', '.pdf'])) {
        alert('仅支持图片和 PDF');
        return;
    }
    if (!FileUtils.isWithinSize(file, 10 * 1024 * 1024)) {
        alert('文件不能超过 10MB');
        return;
    }
    console.log('文件信息:', file.name, FileUtils.formatSize(file.size));
});

八、常见问题与解决方案

常见问题

如何获取文件夹中的所有文件?

使用 webkitdirectory 属性可以选择整个文件夹,但这是非标准属性,兼容性有限。示例:<input type="file" webkitdirectory>

如何重置 file input?

通过设置 input.value = '' 可以重置文件输入,允许用户再次选择相同的文件。

File 对象可以在不同页面间传递吗?

File 对象不能通过 postMessage 传递给其他窗口(包括 iframe),但可以通过结构化克隆在 Worker 间传递。

如何判断文件是否为图片?

可以通过检查 MIME 类型或文件扩展名来判断:file.type.startsWith('image/') 或使用正则表达式匹配扩展名。

九、总结

File API 提供了在客户端获取文件元数据的能力,通过 <input type="file"> 和拖放操作获取 File 对象,可以读取文件名、大小、类型、修改时间等信息。结合 Blob 的 slice 方法可以实现大文件分片处理。使用时需注意客户端验证不可替代服务端验证、大文件分片处理、文件类型和大小限制等最佳实践。File API 是文件上传、文件预览等功能的底层基础,通常与 FileReader API 配合使用来读取文件内容。

标签: File API 文件上传 拖放API Blob 文件分片 HTML5

本文涉及AI创作

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

list快速访问

上一篇: HTML5 API:HTML5 Page Visibility API - 完整教程与代码示例 下一篇: HTML5 API:HTML5 FileReader API - 完整教程与代码示例

poll相关推荐