最近公司專案開始利用 application/json 作為前後端溝通的檔案格式,意味著沒辦法像以前一樣在表單內用 multipart/form-data 格式上傳檔案了。前幾天算是找到一個解法,趁著記憶猶新分享一下。
雖然 json 是目前最流行的檔案交換格式,大部分的 API 都是以這個格式傳送資料,但它最大的問題就是沒辦法放二進位檔案內容。為了解決這個問題,我們需要把二進位檔案內容轉換成可以用文字表達的形式,這時候就輪到 DataURL 出馬了。
dataURL 是一種把檔案內容轉換成一行「類網址」的呈現方式,最大好處是可以將檔案內嵌在網頁中,而不用再發送封包請求跟主機要檔案。以下是一個 dataURL 的範例:data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==
data:
代表它是 DataURLtext/plain;
這是 MIME 類型的宣告,代表它的檔案格式base64,
編碼方式SGVsbG8sIFdvcmxkIQ==
經過編碼的二進位檔案內容知道了上面的 DataURL 之後,我們需要瀏覽器提供的方便功能把 file 轉換成 DataURL。
...
<input type="file" name="myfile">
...
const file = document.querySelector("input[name=myfile]")
const reader = new FileReader()
const dataURL = FileReader.readAsDataURL(file)
console.log(dataURL)
透過以上方是我們可以很順利地把檔案轉換成可以透過 json 傳送的字串,再來就是打包成 json 透過 axios 送出,然後在後端利用 base64_decode 的方式把那段 dataURL 再轉成 file 了。
擺脫了 multipart/form-data 之後,相信透過 application/json 傳送資料又更加方便了
需要小小注意的地方是經過 base64 編碼之後的內容都會膨脹約 33% 的容量,如果要上傳容量較大的檔案需要注意後端主機是否接受?另外瀏覽器也有限制 dataURL 的長度上限,詳情可參考 Data_URLs - MDN 內的長度限制段落
以上,今天分享到這裡,謝謝大家縮看,我們明天見~
[^1]: Data_URLs - MDN
[^2]: FileReader.readAsDataURL() - Web APIs | MDN