Skip to content

File API 与 Blob APi

File 类型

  • 每一个 <input type="file" /> 输入的文件都是一个 FIle 对象
  • 可以通过 new File() 在内存中创意一个文件
    • 第一个参数是一个字符串数组。数组中的每一个元素对应着文件中一行的内容
    • 第二个参数就是文件名字符串
    • 第三个参数可以设定一些文件的属性
js
new File(["hello world", "baibai"], fileName, { type: "text/plain" })
  • 每个 File 对象都有一些只读属性
属性说明
name本地系统中的文件名
size以字节计的文件大小
type包含文件 MIME 类型的字符串
lastModifiedDate表示文件最后修改时间的字符串
此属性只有 Chrome 实现了

监听 inputchange 事件,即可获取到输入的文件

js
const files = document.getElementsByTagName('input')[0]
files.addEventListener('change', e => {
    console.log(e.target.files)
})

拖拽事件,可以从 event.dataTransfer.files 中读取文件列表

FileReader 类型

  • 可以进行异步文件读取
  • 提供了 4 个读取文件数据的方法和一个终止读取的方法
方法说明
readAsText(file, encoding)从文件中读取纯文本内容,并保存在 result 属性中
第二个参数表示编码,是可选的
readAsDataURL(file)读取文件并将内容的数据 URI 保存在 result 属性中
readAsBinaryString(file)读取文件并将每个字符的二进制数据保存在 result 属性中
readAsArrayBuffer(file)读取文件并将文件内容以 ArrayBuffer 形式保存在 result 属性中
abort()提前结束文件读取
  • 还有以下几个相关事件
事件说明
progress读取的进度,每 50 毫秒触发一次。其上有 lengthComputableloadedtotal 属性
在这过程中可以读取 FileReaderresult 属性,即使尚未包含全部数据
errror由于某种原因无法读取文件时触发。其有一个 code 属性
1:未找到文件;2:安全错误;3:读取被中断;4:文件不可读;5:编码错误
load文件成功加载后触发
abort调用 abort() 方法后触发
loadendloaderrorabort 事件触发后,触发

下面进行一些演示

js
const files = document.getElementsByTagName('input')[0]

files.addEventListener('change', e => {
    const progress = document.getElementsByTagName('progress')[0], // 进度条
          output = document.getElementById('output')               // 输出的 DOM
          file = e.target.files[0],                                  
          reader = new FileReader()
    let type = ''

    if (/image/.test(file.type)) { // 根据不同文件类型,调用不同方法
        reader.readAsDataURL(file)
        type = 'image'
    } else {
        reader.readAsText(file)
        type = 'text'
    }

    reader.addEventListener('error', error => {
        output.innerHTML = error.code
    })

    reader.addEventListener('progress', e => {
        if (e.lengthComputable) {
            progress.value = Math.round( (e.loaded / e.total) * 100)
        }
    })

    reader.addEventListener('load', () => {
        let html = ''
        switch(type) {
            case 'image':
                html = `<img src="${reader.result}" />`
                break;
            case 'text':
                html = reader.result
                break;
        }
        output.innerHTML = html
    })
})

FileReadSync 类型

  • FileReader 的同步版本,拥有相同的方法和事件
  • 此类型只能在工作线程中使用,因为读取文件耗时太长会影响全局
js
// worker.js
self.onmessage = e => {
    const syncReader = new FileReaderSync()
    const result = syncReader.readAsDataURI(e.data)
    self.postMessage(result)
}

Blob 类型

  • 二进制大对象,是对不可修改二进制数据的封装类型

  • 有两个属性:size 属性和 type 属性

    js
    new Blob(['<div>foo</div>'], { type: 'text/html' }) // Blob {size: 14, type: "text/html"}
  • 有一个方法:slice() 用于进一步切分数据。如读取文件的前 32 个字节

js
const files = document.getElementsByTagName('input')[0]

files.addEventListener('change', e => {
    const reader = new FileReader(),
          blob = blobSlice(e.target.files[0], 0, 32)

    if (blob) {
        reader.readAsText(blob)
        reader.addEventListener('load', () => {
            console.log(reader.result)
        })
    }
})

获取内存图片

  • 可以使用 window.URL.createObjectURL() 方法,返回一个指向内存中地址的字符串
js
const files = document.getElementsByTagName('input')[0]

files.addEventListener('change', e => {
    const output = document.getElementById('output')
          file = e.target.files[0],
          url = window.URL.createObjectURL(file)
    if (url) {
        if (/image/.test(file.type)) {
            output.innerHTML = `<img src=${url} />`
        } else {
            output.innerHTML = 'it is not a image'
        }
    }
})