Javascript怎么读取上传文件内容/类型/字节数

发布时间:2022-05-07 10:56:14 作者:iii
来源:亿速云 阅读:670
# JavaScript怎么读取上传文件内容/类型/字节数

## 目录
1. [文件上传基础](#文件上传基础)
2. [获取文件对象](#获取文件对象)
3. [读取文件元信息](#读取文件元信息)
   - [文件类型检测](#文件类型检测)
   - [文件大小限制](#文件大小限制)
4. [读取文件内容](#读取文件内容)
   - [文本文件读取](#文本文件读取)
   - [二进制文件处理](#二进制文件处理)
5. [高级文件操作](#高级文件操作)
   - [大文件分片读取](#大文件分片读取)
   - [图片预览生成](#图片预览生成)
6. [安全注意事项](#安全注意事项)
7. [完整代码示例](#完整代码示例)
8. [浏览器兼容性](#浏览器兼容性)

## 文件上传基础

在Web开发中,文件上传是常见需求。HTML5提供了`<input type="file">`元素实现文件选择功能:

```html
<input type="file" id="fileInput">

当用户选择文件后,可以通过JavaScript访问File API来获取文件信息。现代浏览器支持以下核心对象:

获取文件对象

通过DOM获取文件对象的基本方法:

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

fileInput.addEventListener('change', (event) => {
  const files = event.target.files; // FileList对象
  if (files.length > 0) {
    const firstFile = files[0];
    console.log('获取到文件:', firstFile);
  }
});

读取文件元信息

每个File对象包含以下重要属性:

属性名 类型 描述
name String 文件名(不含路径)
size Number 文件大小(字节)
type String MIME类型
lastModified Number 最后修改时间戳
lastModifiedDate Date 最后修改日期对象

文件类型检测

实际开发中需要注意:

  1. 不要依赖文件扩展名判断类型
  2. MIME类型可能为空或不准确
  3. 推荐结合文件签名(魔数)验证
// 实际文件类型检测函数
function checkFileType(file, expectedTypes) {
  const typeMap = {
    'image/png': [0x89, 0x50, 0x4E, 0x47],
    'image/jpeg': [0xFF, 0xD8, 0xFF]
  };
  
  return new Promise((resolve) => {
    const reader = new FileReader();
    reader.onload = (e) => {
      const arr = new Uint8Array(e.target.result.slice(0,4));
      const header = Array.from(arr).map(b => b.toString(16));
      const isExpected = expectedTypes.some(type => {
        const signature = typeMap[type];
        return signature.every((byte, i) => byte === arr[i]);
      });
      resolve(isExpected);
    };
    reader.readAsArrayBuffer(file.slice(0,4));
  });
}

文件大小限制

前端验证文件大小示例:

const MAX_SIZE = 10 * 1024 * 1024; // 10MB

function validateFileSize(file) {
  if (file.size > MAX_SIZE) {
    alert(`文件大小不能超过${MAX_SIZE/1024/1024}MB`);
    return false;
  }
  return true;
}

读取文件内容

文本文件读取

使用FileReader读取文本内容:

function readTextFile(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result);
    reader.onerror = reject;
    reader.readAsText(file);
  });
}

// 使用示例
readTextFile(someFile)
  .then(content => console.log(content))
  .catch(err => console.error(err));

二进制文件处理

处理二进制数据的几种方式:

  1. ArrayBuffer: 原始二进制数据
  2. DataView: 类型化数组视图
  3. Blob: 不可变原始数据对象
// 读取二进制数据并计算SHA-256哈希
async function calculateFileHash(file) {
  const buffer = await file.arrayBuffer();
  const hashBuffer = await crypto.subtle.digest('SHA-256', buffer);
  const hashArray = Array.from(new Uint8Array(hashBuffer));
  return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}

高级文件操作

大文件分片读取

处理大文件时推荐分片读取:

const CHUNK_SIZE = 1 * 1024 * 1024; // 1MB

async function* chunkFile(file) {
  let offset = 0;
  while (offset < file.size) {
    const chunk = file.slice(offset, offset + CHUNK_SIZE);
    const buffer = await chunk.arrayBuffer();
    yield buffer;
    offset += CHUNK_SIZE;
  }
}

// 使用示例
for await (const chunk of chunkFile(largeFile)) {
  // 处理每个分片
}

图片预览生成

生成图片预览的两种方式:

  1. URL.createObjectURL()

    function createImagePreview(file) {
     const img = document.createElement('img');
     img.src = URL.createObjectURL(file);
     img.onload = () => URL.revokeObjectURL(img.src);
     return img;
    }
    
  2. Canvas压缩预览

    async function createCompressedPreview(file, maxWidth = 300) {
     const img = await createImageBitmap(file);
     const canvas = document.createElement('canvas');
     const ratio = maxWidth / img.width;
     canvas.width = maxWidth;
     canvas.height = img.height * ratio;
    
    
     const ctx = canvas.getContext('2d');
     ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
     return canvas.toDataURL('image/jpeg', 0.8);
    }
    

安全注意事项

  1. 永远不要信任客户端验证:必须进行服务端验证
  2. 防止恶意文件上传
    • 检查文件签名
    • 限制可执行文件上传
    • 使用病毒扫描服务
  3. 内容安全策略(CSP):防止XSS攻击
  4. 临时文件清理:及时释放ObjectURL

完整代码示例

<!DOCTYPE html>
<html>
<head>
  <title>文件上传示例</title>
  <style>
    #preview { max-width: 300px; max-height: 300px; }
    .progress { width: 100%; background: #f0f0f0; }
    .progress-bar { height: 20px; background: #4CAF50; width: 0%; }
  </style>
</head>
<body>
  <input type="file" id="fileInput" multiple>
  <div id="fileInfo"></div>
  <img id="preview">
  <div class="progress">
    <div class="progress-bar"></div>
  </div>
  
  <script>
    const fileInput = document.getElementById('fileInput');
    const fileInfo = document.getElementById('fileInfo');
    const preview = document.getElementById('preview');
    const progressBar = document.querySelector('.progress-bar');

    fileInput.addEventListener('change', async (event) => {
      const files = event.target.files;
      if (files.length === 0) return;
      
      const file = files[0];
      
      // 显示文件信息
      fileInfo.innerHTML = `
        <p>文件名: ${file.name}</p>
        <p>文件类型: ${file.type || '未知'}</p>
        <p>文件大小: ${(file.size / 1024).toFixed(2)} KB</p>
        <p>最后修改: ${new Date(file.lastModified).toLocaleString()}</p>
      `;
      
      // 图片预览
      if (file.type.startsWith('image/')) {
        preview.src = URL.createObjectURL(file);
        preview.onload = () => URL.revokeObjectURL(preview.src);
      }
      
      // 分片读取示例
      if (file.size > 5 * 1024 * 1024) {
        let uploaded = 0;
        for await (const chunk of chunkFile(file)) {
          uploaded += chunk.byteLength;
          const percent = (uploaded / file.size * 100).toFixed(1);
          progressBar.style.width = `${percent}%`;
          progressBar.textContent = `${percent}%`;
          // 这里可以发送分片到服务器
          await new Promise(r => setTimeout(r, 100)); // 模拟上传延迟
        }
      }
    });
    
    async function* chunkFile(file, chunkSize = 1 * 1024 * 1024) {
      let offset = 0;
      while (offset < file.size) {
        const chunk = file.slice(offset, offset + chunkSize);
        yield await chunk.arrayBuffer();
        offset += chunkSize;
      }
    }
  </script>
</body>
</html>

浏览器兼容性

特性 Chrome Firefox Safari Edge IE
File API 7+ 3.6+ 6+ 10+ 10+
FileReader 7+ 3.6+ 6+ 10+ 10+
Blob 20+ 13+ 6+ 12+ 10+
File.slice() 21+ 13+ 6.1+ 12+ 10+
File.arrayBuffer() 76+ 69+ 14+ 79+

对于旧版浏览器,可以考虑使用第三方库如: - Resumable.js - Flow.js - FileSaver.js

”`

这篇文章详细介绍了JavaScript处理文件上传的各个方面,从基础操作到高级技巧,包含了约2900字的内容。文章采用Markdown格式编写,包含代码示例、表格和结构化目录,适合作为技术文档或博客文章发布。

推荐阅读:
  1. java _io_commons读取、写出文件
  2. Javascript如何读取上传文件内容/类型/字节数

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

javascript

上一篇:JavaScript+layui下拉框不显示怎么解决

下一篇:怎么使用javascript函数编写银行取钱存钱

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》