天天看點

.dat檔案寫入byte類型數組_來聊聊如何對檔案進行讀取、裁剪、下載下傳

點選上方“ 前端印象 ”,選擇“ 設為星标 ” 第一時間關注技術幹貨!

最開始的一個小需求

前兩天項目中有個小需求:前端下載下傳背景小哥傳回的二進制流檔案。

起初接到這個需求時,我感覺這很簡單啊(雖然我不會,但可以百度啊,,,,)

.dat檔案寫入byte類型數組_來聊聊如何對檔案進行讀取、裁剪、下載下傳

然後就寫出了如下的代碼:

這一段代碼,我大概強行解釋一下:

首先判斷

window.navigator.msSaveOrOpenBlob

是為了相容

IE

(誰要相容這 xx

IE

!!)

然後非

IE

的通過

URL.createObjectURL()

Blob

(

Blob

是啥?不知道?沒關系,我下面會具體裝逼講解的)建構為一個

object URL

對象、指定檔案名&檔案類型、建立

a

連結模拟點選實作下載下傳,最後通過

URL.revokeObjectURL

釋放建立的對象。

功能雖然實作了,但其實我是似懂非懂的~

.dat檔案寫入byte類型數組_來聊聊如何對檔案進行讀取、裁剪、下載下傳

緊接着 一個不那麼簡單的需求

沒過幾天,産品又給我提了一個需求:圖檔裁剪上傳及預覽。

雖然聽過類似的需求,但自己手寫還真的沒寫過,然後我就開始了網上沖浪時光(各種搜尋,,,)。但這次,沒有想象中那麼簡單了~~

網上看到的都是諸如

FileReader

canvas

ArrayBuffer

FormData

Blob

這些名詞。我徹底懵了,這些平時都隻是聽過啊,用的也不多啊。經過了一番學習,我發現這些都屬于前端二進制的知識範疇,是以在搞業務前,我準備先把涉及到的前端二進制梳理一遍,正所謂:底層基礎決定上層建築嘛 🙈

.dat檔案寫入byte類型數組_來聊聊如何對檔案進行讀取、裁剪、下載下傳

FileReader

HTML5

定義了

FileReader

作為檔案

API

的重要成員用于讀取檔案,根據

W3C

的定義,

FileReader

接口提供了讀取檔案的方法和包含讀取結果的事件模型。

建立執行個體

方法

方法名 描述

abort

中止讀取操作

readAsArrayBuffer

異步按位元組讀取檔案内容,結果用

ArrayBuffer

對象表示

readAsBinaryString

異步按位元組讀取檔案内容,結果為檔案的二進制串

readAsDataURL

異步讀取檔案内容,結果用

data:url

的字元串形式表示

readAsText

異步按字元讀取檔案内容,結果用字元串形式表示

事件

事件名 描述

onabort

中斷時觸發

onerror

出錯時觸發

onload

檔案讀取成功完成時觸發

onloadend

讀取完成觸發(無論成功或失敗)

onloadstart

讀取開始時觸發

onprogress

讀取中

示例

下面我們嘗試把一個檔案的内容通過字元串的方式讀取出來:

ArrayBuffer

/

TypedArray

/

DataView 對象

ArrayBuffer

先來看下

ArrayBuffer

的功能:

.dat檔案寫入byte類型數組_來聊聊如何對檔案進行讀取、裁剪、下載下傳

先來介紹

ArrayBuffer

,是因為

FileReader

有個

readAsArrayBuffer()

的方法,如果被讀的檔案是二進制資料,那用這個方法去讀應該是最合适的,讀出來的資料,就是一個

Arraybuffer

對象,來看下定義:

ArrayBuffer

對象用來表示通用的、固定長度的原始二進制資料緩沖區.

ArrayBuffer

不能直接操作,而是要通過類型數組對象或

DataView

對象來操作,它們會将緩沖區中的資料表示為特定的格式,并通過這些格式來讀寫緩沖區的内容.

ArrayBuffer

也是一個構造函數,可以配置設定一段可以存放資料的連續記憶體區域。

由于無法對

Arraybuffer

直接進行操作,是以我們需要借助其他對象來操作. 所有就有了

TypedArray

(類型數組對象)和

DataView

對象。

DataView 對象

上面代碼生成了一段 8 位元組的記憶體區域,每個位元組的值預設都是 0。

為了讀寫這段内容,需要為它指定視圖。

DataView

視圖的建立,需要提供

ArrayBuffer

對象執行個體作為參數。

DataView

視圖是一個可以從二進制

ArrayBuffer

對象中讀寫多種數值類型的底層接口。

  • setint8()

    DataView

    起始位置以

    byte

    為計數的指定偏移量(

    byteOffset

    )處存儲一個

    8-bit

    數(一個位元組)
  • getint8()

    DataView

    起始位置以

    byte

    為計數的指定偏移量(

    byteOffset

    )處擷取一個

    8-bit

    數(一個位元組)

調用

示例

.dat檔案寫入byte類型數組_來聊聊如何對檔案進行讀取、裁剪、下載下傳

TypedArray

另一種

TypedArray

視圖,與

DataView

視圖的一個差別是,它不是一個構造函數,而是一組構造函數,代表不同的資料格式。

TypedArray

對象描述了一個底層的二進制資料緩存區(

binary data buffer

)的一個類數組視圖(

view

)。

但它本身不可以被執行個體化,甚至無法通路,你可以把它了解為接口,它有很多的實作。

實作方法

類型 單個元素值的範圍 大小(bytes) 描述
Int8Array -128 to 127 1 8 位二進制有符号整數
Uint8Array 0 to 255 1 8 位無符号整數
Int16Array -32768 to 32767 2 16 位二進制有符号整數
Uint16Array 0 to 65535 2 16 位無符号整數

示例

Blob

Blob

是用來支援檔案操作的。簡單的說:在

JS

中,有兩個構造函數

File

Blob

, 而

File

繼承了所有

Blob

的屬性。

是以在我們看來,

File

對象可以看作一種特殊的

Blob

對象。

上面說了,

File

對象是一種特殊的

Blob

對象,那麼它自然就可以直接調用

Blob

對象的方法。讓我們看一看

Blob

具體有哪些方法,以及能夠用它們實作哪些功能:

.dat檔案寫入byte類型數組_來聊聊如何對檔案進行讀取、裁剪、下載下傳

是的,我們這裡更加傾向于實戰中的應用~

.dat檔案寫入byte類型數組_來聊聊如何對檔案進行讀取、裁剪、下載下傳

關于

Blob

的更具體介紹可以參考Blob[1]

atob

btoa

base64

相信大家都不會陌生吧(不知道的看這裡[2]),最常用的操作可能就是圖檔轉

base64

了吧?

在之前要在字元串跟

base64

之間互轉,我們可能需要去網上拷一個别人的方法,而且大部分情況下,你沒有時間去驗證這個方法是不是真的可靠,有沒有

bug

IE10+

浏覽器開始,所有浏覽器就原生提供了

Base64

編碼解碼方法。

Base64 解碼

Base64 編碼

Canvas

中的

ImageData

對象

關于

Canvas

,這裡我就不做過多介紹了,具體可參考canvas 文檔[3]

今天主要說一下

Canvas

中的

ImageData

對象(也是為下面的那個圖檔裁剪的項目做一些基礎知識的鋪墊~)

.dat檔案寫入byte類型數組_來聊聊如何對檔案進行讀取、裁剪、下載下傳

ImageData

對象中存儲着

canvas

對象真實的像素資料,它包含以下幾個隻讀屬性:

  • width

    :圖檔寬度,機關是像素
  • height

    :圖檔高度,機關是像素
  • data

    Uint8ClampedArray

    類型的一維數組,包含着

    RGBA

    格式的整型資料,範圍在 0 至 255 之間(包括 255)。

建立一個

ImageData

對象

使用

createImageData()

方法去建立一個新的,空白的

ImageData

對象。

上面代碼建立了一個新的具體特定尺寸的

ImageData

對象。所有像素被預設為透明黑。

得到場景像素資料

為了獲得一個包含畫布場景像素資料的

ImageData

對象,你可以用

getImageData()

方法:

在場景中寫入像素資料

你可以用

putImageData()

方法去對場景進行像素資料的寫入。

toDataURL

canvas

轉為

data URI

格式

有如下

元素:

可以用下面的方式擷取一個

data-URL

到這裡,二進制相關的基礎知識我已經鋪墊完了。下面讓我們回到文章開頭提到的那個産品的“沒那麼簡單”的新需求:圖檔裁剪上傳及預覽。

其實,像

圖檔裁剪上傳

這種社群已經有非常成熟的解決方案了,如vue-cropper[4]。這裡,我選擇手寫一個簡易的圖檔裁剪的目的是因為這其中用到了上文提及的大量的二進制知識,可以很好的将理論與實踐結合。

話不多說,開 Giao!!

.dat檔案寫入byte類型數組_來聊聊如何對檔案進行讀取、裁剪、下載下傳

需求開發 Giao Giao!

先來看下最終的效果:

.dat檔案寫入byte類型數組_來聊聊如何對檔案進行讀取、裁剪、下載下傳

這裡貼下完成後的代碼位址[5]

另外,我用一張圖梳理了以上提到的前端二進制子產品的關系,這對于下面需求的開發會有很大的幫助:

.dat檔案寫入byte類型數組_來聊聊如何對檔案進行讀取、裁剪、下載下傳

整個需求分以下四步:

1、擷取檔案并讀取檔案。

2、擷取裁剪坐标。

3、裁剪圖檔。

4、讀取裁剪後的圖檔預覽并上傳。

擷取檔案并讀取檔案

首先來看下上面第一步提到的擷取檔案。對應就是給

input

綁定的

handleChange

事件:

HTML5

支援從

input[type=file]

元素中直接擷取檔案資訊,也可以讀取檔案内容。

這裡就需要用到了

FileReader

,這個類是專門用來讀取本地檔案的。純文字或者二進制都可以讀取,但是本地檔案必須是經過使用者允許才能讀取,也就是說使用者要在

input[type=file]

中選擇了這個檔案,你才能讀取到它。

通過

FileReader

我們可以将圖檔檔案轉化成

DataURL

,就是以

data:image/png;base64

開頭的一種

URL

,然後可以直接放在

image.src

裡,這樣本地圖檔就顯示出來了。

擷取裁剪坐标

這裡主要是

mousedown

mousemove

mouseup

事件的結合使用。

mousedown

滑鼠按下事件。這裡要記錄下滑鼠按下時的開始坐标,即

startX

startY

,同時要将标志位

startDrag

設為

true

,辨別滑鼠開始移動。

mousemove

滑鼠移動事件。判斷

startDrag

true

(即滑鼠開始移動),然後記錄對應移動的距離。

mouseup

滑鼠彈起事件。這裡要記錄下最終滑鼠的落點坐标,對應就是

lastX

lastY

裁剪圖檔

這個時候我們就需要用到

canvas

了,

canvas

和圖檔一樣,是以建立

canvas

時就要确定其高寬。

将圖檔放置入

canvas

時需要調用

drawImage

具體

API

使用參考

MDN

上的drawImage[6]

其中這裡面我們還加入了

scale

,這個變量是用來實作圖檔

放大

縮小

效果的。

而且會判斷圖檔的寬、高的大小關系,進而實作圖檔在

canvas

中對應的适配。

讀取裁剪後的圖檔并上傳

這時我們要擷取

canvas

中圖檔的資訊,用

toDataURL

就可以轉換成上面用到的

DataURL

然後取出其中

base64

資訊,再用

window.atob

轉換成由二進制字元串。但

window.atob

轉換後的結果仍然是字元串,直接給

Blob

還是會出錯。是以又要用

Uint8Array

轉換一下。

這時候裁剪後的檔案就儲存在

blob

裡了,我們可以把它當作是普通檔案一樣,加入到

FormData

裡,并上傳至伺服器了。

.dat檔案寫入byte類型數組_來聊聊如何對檔案進行讀取、裁剪、下載下傳

👇👇👇  歡迎留言讨論  👇👇👇 推薦閱讀

.dat檔案寫入byte類型數組_來聊聊如何對檔案進行讀取、裁剪、下載下傳

 【JS面試題】用四種方式實作數組扁平化你會嗎

.dat檔案寫入byte類型數組_來聊聊如何對檔案進行讀取、裁剪、下載下傳

 【JS面試題】數組去重(6種方法)震驚面試官

.dat檔案寫入byte類型數組_來聊聊如何對檔案進行讀取、裁剪、下載下傳

 【超高頻面試題】這兩段代碼的傳回結果你知道是什麼嗎?

.dat檔案寫入byte類型數組_來聊聊如何對檔案進行讀取、裁剪、下載下傳

 【css面試題】用css畫0.5px的線條

.dat檔案寫入byte類型數組_來聊聊如何對檔案進行讀取、裁剪、下載下傳

 【css面試題】css實作氣泡框效果

.dat檔案寫入byte類型數組_來聊聊如何對檔案進行讀取、裁剪、下載下傳

 【css炫酷動畫】讓面試官眼前一亮的故障風格文字動畫

.dat檔案寫入byte類型數組_來聊聊如何對檔案進行讀取、裁剪、下載下傳

END

❤支援三連

1.看到這裡了就點個在看支援下吧,你的「在看」是我創作的動力。

2.關注公衆号

前端印象

,「一起交流進步」!

3.關注公衆号回複【加群】,拉你進技術交流群一起玩轉前端。

.dat檔案寫入byte類型數組_來聊聊如何對檔案進行讀取、裁剪、下載下傳

點贊、在看、分享 支援作者❤️

繼續閱讀