喔唷网 - 网络从业者技术信息综合门户!

当前位置: 主页 > 教程技术 > 编程语言 > html/css

HTML5 文件API让web也能访问本地文件 11.3

时间 : 2025-04-27 11:14来源 : 喔唷网作者 : 喔唷教程点击 :
HTML5文件API(File API)为Web应用程序提供了访问用户本地文件系统的能力,使开发者能够实现文件读取、处理和上传等功能,而无需依赖传统的表单上传方式。 11.3.1 核心接口 文件API包含以下几个关键

HTML5文件API(File API)为Web应用程序提供了访问用户本地文件系统的能力,使开发者能够实现文件读取、处理和上传等功能,而无需依赖传统的表单上传方式。

11.3.1 核心接口

文件API包含以下几个关键接口:

  1. File:表示文件系统中的单个文件,包含只读属性:name:文件名size:文件大小(字节)type:文件MIME类型lastModified:最后修改时间戳lastModifiedDate:最后修改日期对象
  2. FileList:表示文件列表,通常来自<input type="file">元素的files属性
  3. FileReader:用于异步读取文件内容
  4. Blob(Binary Large Object):表示不可变的原始数据块

11.3.2 基本使用

通过input元素选择文件

<input type="file" id="fileInput" multiple>
<script>
  document.getElementById('fileInput').addEventListener('change', function(e) {
    const files = e.target.files; // 获取FileList对象
    processFiles(files);
  });
  
  function processFiles(files) {
    for (let i = 0; i < files.length; i++) {
      const file = files[i];
      console.log(`文件名: ${file.name}, 类型: ${file.type}, 大小: ${file.size}字节`);
    }
  }
</script>

通过拖放选择文件

<div id="dropZone" style="width:300px;height:200px;border:2px dashed #ccc;">
  拖放文件到此处
</div>
<script>
  const dropZone = document.getElementById('dropZone');
  
  dropZone.addEventListener('dragover', function(e) {
    e.preventDefault();
    this.style.borderColor = '#666';
  });
  
  dropZone.addEventListener('dragleave', function() {
    this.style.borderColor = '#ccc';
  });
  
  dropZone.addEventListener('drop', function(e) {
    e.preventDefault();
    this.style.borderColor = '#ccc';
    
    const files = e.dataTransfer.files;
    processFiles(files);
  });
</script>

11.3.3 FileReader读取文件内容

FileReader提供了几种读取文件的方法:

  1. readAsText(file[, encoding]):读取为文本
  2. readAsDataURL(file):读取为Data URL(Base64编码)
  3. readAsArrayBuffer(file):读取为ArrayBuffer
  4. readAsBinaryString(file):读取为二进制字符串(已废弃)

示例:读取文本文件

function readTextFile(file) {
  const reader = new FileReader();
  
  reader.onload = function(e) {
    console.log('文件内容:', e.target.result);
  };
  
  reader.onerror = function() {
    console.error('读取文件时出错');
  };
  
  reader.readAsText(file);
}

示例:预览图片

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

11.3.4 文件切片与分块上传

利用Blob.slice()方法可以实现大文件分块上传:

function uploadInChunks(file, chunkSize = 1024 * 1024) { // 默认1MB
  const chunks = Math.ceil(file.size / chunkSize);
  let currentChunk = 0;
  
  function uploadNextChunk() {
    const start = currentChunk * chunkSize;
    const end = Math.min(start + chunkSize, file.size);
    const chunk = file.slice(start, end);
    
    const formData = new FormData();
    formData.append('file', chunk);
    formData.append('chunkIndex', currentChunk);
    formData.append('totalChunks', chunks);
    formData.append('fileName', file.name);
    
    fetch('/upload', {
      method: 'POST',
      body: formData
    }).then(response => {
      currentChunk++;
      if (currentChunk < chunks) {
        uploadNextChunk();
      } else {
        console.log('上传完成');
      }
    });
  }
  
  uploadNextChunk();
}

11.3.5 文件系统访问API

现代浏览器还提供了更强大的文件系统访问API:

// 请求文件句柄
async function getFileHandle() {
  try {
    const handle = await window.showOpenFilePicker({
      types: [{
        description: 'Text Files',
        accept: {'text/plain': ['.txt']}
      }],
      multiple: false
    });
    
    const file = await handle[0].getFile();
    console.log('获取的文件:', file);
    
    return handle;
  } catch (err) {
    console.error('用户取消选择或发生错误', err);
  }
}

// 写入文件
async function saveFile(contents) {
  try {
    const handle = await window.showSaveFilePicker({
      types: [{
        description: 'Text Files',
        accept: {'text/plain': ['.txt']}
      }]
    });
    
    const writable = await handle.createWritable();
    await writable.write(contents);
    await writable.close();
    
    console.log('文件保存成功');
  } catch (err) {
    console.error('保存文件失败', err);
  }
}

11.3.6 文件验证

在处理用户上传的文件时,验证非常重要:

function validateFile(file) {
  // 验证文件类型
  const allowedTypes = ['image/jpeg', 'image/png', 'application/pdf'];
  if (!allowedTypes.includes(file.type)) {
    throw new Error('不支持的文件类型');
  }
  
  // 验证文件大小 (5MB限制)
  const maxSize = 5 * 1024 * 1024;
  if (file.size > maxSize) {
    throw new Error('文件大小超过5MB限制');
  }
  
  // 验证文件名
  if (!/^[\w\-\. ]+$/.test(file.name)) {
    throw new Error('文件名包含非法字符');
  }
  
  return true;
}

11.3.7 实际应用示例

图片压缩上传

async function compressAndUpload(file, quality = 0.7) {
  return new Promise((resolve, reject) => {
    if (!file.type.match('image.*')) {
      reject(new Error('不是图片文件'));
      return;
    }
    
    const reader = new FileReader();
    reader.onload = function(e) {
      const img = new Image();
      img.onload = function() {
        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d');
        
        // 计算压缩后尺寸
        let width = img.width;
        let height = img.height;
        const maxDimension = 1600;
        
        if (width > height && width > maxDimension) {
          height *= maxDimension / width;
          width = maxDimension;
        } else if (height > maxDimension) {
          width *= maxDimension / height;
          height = maxDimension;
        }
        
        canvas.width = width;
        canvas.height = height;
        ctx.drawImage(img, 0, 0, width, height);
        
        // 转换为Blob并上传
        canvas.toBlob(blob => {
          const compressedFile = new File([blob], file.name, {
            type: 'image/jpeg',
            lastModified: Date.now()
          });
          
          uploadFile(compressedFile).then(resolve).catch(reject);
        }, 'image/jpeg', quality);
      };
      img.src = e.target.result;
    };
    reader.readAsDataURL(file);
  });
}

function uploadFile(file) {
  const formData = new FormData();
  formData.append('image', file);
  
  return fetch('/api/upload', {
    method: 'POST',
    body: formData
  }).then(response => response.json());
}

11.3.8 浏览器兼容性

文件API的主要功能在现代浏览器中得到良好支持:

  • Chrome 7+
  • Firefox 3.6+
  • Safari 6+
  • Edge 12+
  • Opera 12+

文件系统访问API是较新的功能,支持度较低:

  • Chrome 86+
  • Edge 86+
  • Firefox和Safari尚未支持

11.3.9 安全注意事项

  1. 用户授权:文件访问必须由用户主动触发(如点击事件)
  2. 敏感信息:某些文件可能包含敏感信息,需谨慎处理
  3. XSS防护:正确处理文件内容,防止XSS攻击
  4. 大小限制:对上传文件实施合理的大小限制
  5. 服务器验证:客户端验证不能替代服务器端验证

11.3.10 最佳实践

  1. 提供清晰的反馈:显示文件选择/上传进度
  2. 处理大文件:使用分块上传和进度事件
  3. 优化性能:对于图片/视频,考虑压缩后再上传
  4. 错误处理:妥善处理各种可能的错误情况
  5. 回退方案:为不支持API的浏览器提供传统表单上传

文件API为Web应用提供了强大的文件处理能力,使开发者能够创建更丰富的用户体验。通过合理使用这些API,可以实现从简单的文件上传到复杂的本地文件系统交互等各种功能。

栏目列表

关联类容

热点推荐

栏目推荐

猜你喜欢