前端的 File API
¶前端的 File API
這一次會將一些與檔案讀寫相關的 JavaScript 與 HTML 一起聊一聊。
而這次會用上的 HTML 都有一個共同的特性,那就是「它們本身代表內容」,但 <textarea>
除外
「HTML tag 本身代表內容」的特殊之處
無法使用偽元素。
因為偽元素是用來修飾容器中的內容的頭尾,若 HTML tag 本身就是內容,就沒有「內容的頭尾」這件事。自然也就不會有偽元素。
所以這些 HTML tag 都會自我結尾。
前端 File API
有幾個要先知道的[1]
- File & Blob: File 是一個有名字的 Blob
- FileList: 以 File 為元素的 List,但它並不是 Array
- FileReader: 用來讀取 File 的內容
- 分成同步和非同步,2 種方式
- 可將檔案轉成四種資料
- 文字
- 二進制陣列 (建議)
- 二進制字串 (不建議)
- Data URL (blob url)
- URL: 用來將 File 使用在其它的 Web 環境中 (包含 DOM tree)
¶地圖
(圖有點大,左右可滑動)
¶從 FileList 取得 File
宣告一個讓瀏覽器讀取檔案的「通道」而 DOM tree 上的 <input type="file" />
其實是一個「檔案列表」的管理控制項
<form method="post" action="upload" name="myForm" enctype="multipart/form-data"> |
在 <form>
使用 name
屬性,像是宣告一樣的直接在 document
裡產生 property
const inputFile = document.myForm.myUploadFile; // <input type="file" name="myUploadFile" /> |
¶從 File 下載
利用 <a href="" />
將檔案轉成 blob url 放到 href
並且點擊,就可以完成下載 blob 檔案的功能。
<button id="downloadFileButton" type="button" name="button">download File</button> |
const downloadFileButton = document.querySelector("#downloadFileButton"); |
- 取得檔案的 blob url
- 設定
<a href="" />
的href
設定成 blob url - 觸發 click 事件。 (如果已使用 a 的 click 進行這一連串的動作,就不用再觸發一次 click)
¶File to Image
在想要做上傳圖片的預覽時,就需要將 <input type="file" />
的內容,放到 <img src="" />
裡。
那實際上是怎麼做到的呢?
<img id="image" src="" alt="" /> |
const inputFile = document.myForm.myUploadFile; // 要先有 <input type=file /> |
- 取出 File
- 產生 Blob url
- img.src = Blob url
¶Image to Canvas
image 到 canvas 算是 canvas 的特別之處,不算是 File API 的內容。 (不過還是放上來了)
繪製到 canvas 之後,會改變 image 的大小。
<canvas id="canvas" width="200" height="10" /> |
const img = document.querySelector("#image"); // 要先有 <image /> |
- 取得 image object (也可以用
new Imgae()
) - 將 image object 丟進 canvas 的
context.drawImage()
第一個參數,就顯示畫面
¶Canvas as Base64
canvas.toDataURL()
的輸出是一個至少還有 “data:” 的 DataURL
[2]
DataURL 依照 MIME type 判斷輸出方式
如果是文字,就會輸出文字,不然就會給 Base64[3]
<textarea id="base64" name="name" rows="8" cols="80"></textarea> |
const canvas = document.querySelector("#canvas"); // 要先有 <canvas /> |
¶File to Base64
上述得到 Base64 的方式是要透過 File -> Blob URL -> <img>
-> <canvas>
-> Base64
可以直接得到 Base64 嗎?
¶File to text
直接從 File 取得「文字檔案」的內容,要使用 FileReader 物件的 readAsText 方法,並且 binding 事件,在讀取結束時,取得檔案內容 (還可以取得其它的資訊)。
<textarea id="text" name="name" rows="8" cols="80"></textarea> |
const text = document.querySelector("#text"); |
- 宣告 FileReader 物件
- 設定 onload 事件,用
e.target.result
取得內容 - 取得 File 物件的 Blob url
- 將 Blob url 放進 FileReader 物件的
readAsText
method
¶File to binary
直接從 File 取得「圖形檔案」的內容,要使用 FileReader 物件的 readAsArrayBuffer 方法,並且 binding 事件,在讀取結束時,取得檔案內容。
<textarea id="binaryString" name="name" rows="8" cols="80"></textarea> |
const binaryString = document.querySelector("#binaryString"); |
- 宣告 FileReader 物件
- 設定 onload 事件,用
e.target.result
取得內容 - 圖形檔案的資料是 0~255 (8 bit 的大小),所以用
new Uint8Array
將內容丟進去建構。[4] - 取得 File 物件的 Blob url
- 將 Blob url 放進 FileReader 物件的
readAsArrayBuffer
method
¶最後
程式碼會同步在 github 更新[5]