前端文件數(shù)據(jù)格式那些事兒
前言
在 Web 開發(fā)中,當(dāng)我們處理文件時(創(chuàng)建,上傳,下載),經(jīng)常會遇到二進(jìn)制數(shù)據(jù)。另一個典型的應(yīng)用場景是圖像處理。
在 JavaScript 中有很多種二進(jìn)制數(shù)據(jù)格式,比如ArrayBuffer,Uint8Array,DataView,Blob,F(xiàn)ile 等等,不過 JavaScript 中的二進(jìn)制數(shù)據(jù)是以非標(biāo)準(zhǔn)方式實現(xiàn)的。
下面我們來了解下這些數(shù)據(jù)格式及相互轉(zhuǎn)換。
本文涉及到File,Blob,TypedArray,data url(Base64),blob url等等。
File
首先,我們還是拿前文的例子來看,顯示用戶選擇的圖片。
我們創(chuàng)建一個頁面。提供選擇圖片功能。
- <!DOCTYPE html>
- <html>
- <head>
- <title>test</title>
- </head>
- <body>
- <input type="file" id="fileInput" name="選擇圖片"/>
- <div class="wrap-image">
- <canvas id="canvas"></canvas>
- </div>
- <script type="text/javascript">
- </script>
- </body>
- </html>
選擇圖片后,需要將圖片顯示到canvas中,我們在上面的script標(biāo)簽中加入下面的代碼:
- const fileInput = document.getElementById('fileInput')
- const canvas = document.getElementById('canvas')
- fileInput.addEventListener('change', (e) => {
- let img = new Image
- const file = e.target.files[0]
- img.src = URL.createObjectURL(file)
- img.onload = () => {
- canvas.width = img.width
- canvas.height = img.height
- const context = canvas.getContext('2d')
- context.drawImage(img, 0, 0)
- }
- }, false)
選擇一張圖片后,change事件中獲取到選擇的文件e.target.files[0]:

File 對象是特殊類型的 Blob,可以用在任意的 Blob 類型的 context 中。
比如 FileReader, URL.createObjectURL(), createImageBitmap(), 及 XMLHttpRequest.send() 都能處理 Blob 和 File。
File 接口也繼承了 Blob 接口的屬性。上圖的Prototype展開可以看到繼承自Blob:

上面是最常見的file獲取方式————從<input type="file">中獲取。
- new File(fileParts, fileName, [options])
- fileParts —— Blob/BufferSource/String 類型值的數(shù)組
- fileName —— 文件名字符串
- options —— 可選對象
FileReader
FileReader 的用途是從 Blob(因此也從 File)對象中讀取數(shù)據(jù)。
它使用事件來傳遞數(shù)據(jù),因為從磁盤讀取數(shù)據(jù)可能比較費時間。
可以讀取為3種格式:

比如將 Blob 讀取為 base64:
- const reader = new FileReader()
- reader.readAsDataURL(file) // 將 Blob 讀取為 base64
使用時選擇哪一種,要看如何使用數(shù)據(jù)。
讀取過程中有下列事件:
1、loadstart: 開始加載
2、progress: 在讀取過程中出現(xiàn)
3、load: 讀取完成,沒有 error
4、abort: 調(diào)用了 abort()取消操作
5、error: 出現(xiàn) error
6、loadend: 讀取完成,無論成功還是失敗
使用最廣泛的是load和error,比如下面的例子:
- <input type="file" onchange="readFile(this)">
- <script>
- const readFile = (input) => {
- const file = input.files[0]
- const reader = new FileReader()
- reader.readAsText(file)
- reader.onload = () => {
- console.log(reader.result) // 結(jié)果
- }
- reader.onerror = () => {
- console.log(reader.error) // error
- }
- }
- </script>
不過大多數(shù)情況下,我們不需要讀取Blob,通過網(wǎng)絡(luò)發(fā)送一個File很容易,像 XMLHttpRequest 或 fetch 等 API 本身就接受 File 對象?;蛘哂肬RL.createObjectURL(file) 創(chuàng)建一個短的 url,并將其賦給 或 。這樣,文件便可以下載文件或者將其呈現(xiàn)為圖像,作為 canvas 等的一部分。
Blob