File和Blob

阅读 1.9k
标签: JavaScript

在前端开发中,经常需要和文件打交道,比如上传文件,下载文件等,在与文件打交道的同时,Blob也会经常出现,那么这个Blob是啥玩意儿?

什么是Blob

Blob这个名字来源最早出现在SQL数据库中,表示Binary Large Object,在JavaScript中,常常表示二进制数据,它是一个指向数据块的引用,先来看看它长啥样:

const aFileParts = ['<div id="app"><b>hey!</b></div>'] // 一个包含DOMString的数组
const oMyBlob = new Blob(aFileParts, { type: 'text/html' })
console.log(oMyBlob)

上面代码通过new Blob()构造函数,构建了一个简单的blob对象,打印出来如下:


Blob只有两个属性,一个size,表示文件的大小,一个type,表示文件类型,看上去挺“寒酸”的。

什么是文件

既然Blob是一个类文件对象,那么真正的文件(File)是啥样呢?

<input type='file' id="myInput" />

我们可以通过本地上传文件获得真正的文件对象:

const inputDOM = document.getElementById('myInput')
inputDOM.onchange = event => {
    const files = event.target.files
    file = files[0]
}

上面的file变量,打印出来如下:


它也有两个属性,sizetype,除此之外,还有一些其他属性,比如namelastModified等。最重要的是,其原型对象的原型对象为Blob,原来如此,File继承自Blob。

说完了File和Blob本身,接下来,我们再来看看它们具体的应用场景。

文件下载:URL.createObjectURL()

在前端开发中,经常需要进行文件下载,当后端通过接口将下载的数据返回到前端后,前端需要做一些定制化的操作,通常将拿到的Blob对应到一个URL上,再进行下载。
blob:http://0.0.0.0:5500/aa7a0993-2116-4ef9-9832-0f06ebc477e0

通过URL.createObjectURL()获得的URL类似上面的样子,然后创建一个a标签,将其值赋值给href属性:

fetch('http://localhost:3000')
    .then(res => res.blob())
    .then(blob => download(blob))

function download(file) {
    const fileUrl = URL.createObjectURL(file)

    const aTag = document.createElement('a')
    aTag.href = fileUrl
    const fileName = 'demo.jpg'
    aTag.download = fileName
    document.body.appendChild(aTag)
    aTag.click()
    aTag.remove()
    URL.revokeObjectURL(fileUrl)
}

注意:最后记得调用URL.revokeObjectURL()来释放这些 URL 对应数据的占用内存。

服务端代码如下:

const http = require('http')
const path = require('path')
const fs = require('fs')

const mimeType = 'image/jpeg' //  'application/pdf'
const fileName = 'AI.jpg'

const server = http.createServer((req, res) => {
  res.setHeader('Access-Control-Allow-Origin', '*')
  res.setHeader('Content-Type', mimeType)

  const filePath = path.join(__dirname, fileName)
  const stream = fs.createReadStream(filePath)
  stream.on('data', function (chunk) {
    res.write(chunk)
  })
  stream.on('end', function () {
    res.end()
  })
})

server.listen(3000)

读取Blob:FileReader

通过上面的例子可以看出,Blob其实是一个“不透明”的大数据块,通过Blob URL只能间接的访问其内容,如果要直接操作其中的数据,有什么办法吗?可以通过FileReader对象,它能够异步读取Blob中的内容。

其中,最常用的一个场景是,读取图片内容,并在页面上显示预览,来看一个例子:

<img src="" height="200" alt="Image preview...">

读取函数如下:

function readBlob(blob) {
    const preview = document.querySelector('img');
    const reader = new FileReader()

    reader.addEventListener("load", function () {
        preview.src = reader.result;
    }, false)

    if (blob) {
        reader.readAsDataURL(blob)
    }
}

图片会被读取为base64格式,类似:data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAkACQAAD/4QpZ...这种格式,当读取完成后,触发load事件,获得的结果会存入result属性中。

参考

  • Blob()-MDN
  • David Flanagan. JavaScript:The Definitive Guide, 6th
最后编辑于: 2022-06-26

评论(0条)

(必填)
复制成功