Noh | エンジニア向け情報共有コミュニティ
Signup / Login

[JS TS] Async / Await を使った File, Blob, ArrayBuffer, Base64 の相互変換関数の紹介

javascript
typescript

投稿日: 2024/07/26

ファイル操作をしているとFile, Blob, ArrayBuffer, Base64等の型に出会ってそれらを相互変換する機会はそれなりにあると思います。
それぞれ私が使っているコードを紹介するのでご活用ください。
JS標準で非同期関数が提供されてる機能については Async / Await で扱いやすくしたものを載せています。
番外編としてURL.createObjectURLについても少し書いてます。

相互変換できれば検証やテストの時にも便利です。

信頼性の加点になる情報としては、例えばfileToArrayBuffer関数、fileToBase64関数、objectURLToBlob は ImgRoller のプロダクトのソースコードで実用しているコードです。パンダと戦うImgRollerをどうぞよろしく。

https://yosidev.com/tools/imgroller/

その他の関数も一応検証してます。

コードはTypeScriptで書いてますが、型を消せばJavascriptでも動くと思います。

FileまたはBlobからの変換

FileとBlobは扱いが近いので、まとめて扱えることが多いです。

FileまたはBlobからArrayBufferへの変換

readAsArrayBufferを使うと変換できますが、Async / Await が使われていないので扱いずらいです。そう思った人のためにAsync / Await で非同期処理をしたコードを紹介します。

export const fileToArrayBuffer = async ( file: File | Blob, ): Promise<ArrayBuffer> => { return new Promise((resolve, reject) => { const reader = new FileReader() reader.onload = () => { if (reader.result instanceof ArrayBuffer) { resolve(reader.result) } else { reject(new Error("FileReader result is not an ArrayBuffer")) } } reader.onerror = () => { reject(reader.error) } reader.readAsArrayBuffer(file) }) }

FileまたはBlobからBase64への変換

readAsDataURLをAsync / Await を用いて扱いやすく変えています。
ポイントとしてはreader.resultはreadAsDataURLを使ってる時点でstring型になるはずですが、型推論的にはArrayBuffer型とNull型も取ります。なので、ArrayBuffer型とNull型を除外しています。as anyで型エラーをつぶしてもいいのですが、こちらの方がきれいかなと思います。

export const fileToBase64 = async (file: File | Blob): Promise<string> => { return new Promise((resolve, reject) => { const reader = new FileReader() reader.onload = (e) => { if (reader.result instanceof ArrayBuffer || reader.result == null) { reject(new Error("FileReader result is not an string")) } else { resolve(reader.result) } } reader.onerror = (e) => { reject(e) } reader.readAsDataURL(file) }) }

Fileからの変換

FileからBlobへの変換

説明することありませんね。
mdnに従って変換するだけです。

export const fileToBlob = (file: File, mimeType: string) => { return new Blob([file], { type: mimeType }) }

Blobからの変換

BlobからのFileへの変換

こちらも説明することありませんね。
mdnに従って変換するだけです。

export const blobToFile = (blob: Blob, filename: string, mimeType: string) => { return new File([blob], filename, { type: mimeType }) }

ArrayBufferからの変換

ArrayBufferからFileへの変換

mdnに従って変換するだけです。

export const arrayBufferToFile = ( arrayBuffer: ArrayBuffer, filename: string, mimeType: string, ) => { return new File([arrayBuffer], filename, { type: mimeType }) }

ArrayBufferからBlobへの変換

mdnに従って変換するだけです。

export const arrayBufferToBlob = ( arrayBuffer: ArrayBuffer, mimeType: string, ) => { return new Blob([arrayBuffer], { type: mimeType }) }

ArrayBufferからbase64への変換

経験上、ArrayBufferからbase64への変換を行う機会はあまりないでしょう。したがって、新たに関数を作るよりは他で紹介した関数を用いて変換するのが良いでしょう。Blobを一度経由します。

export const arrayBufferToBase64 = async ( arrayBuffer: ArrayBuffer, mimeType: string, ) => { return await fileToBase64(arrayBufferToBlob(arrayBuffer, mimeType)) }

base64からの変換

base64からFileへの変換

export const base64ToFile = ( base64: string, filename: string, mimeType: string, ) => { const byteCharacters = atob(base64.split(",")[1]) const byteNumbers = Array.from(byteCharacters, (char) => char.charCodeAt(0)) const byteArray = new Uint8Array(byteNumbers) return new File([byteArray], filename, { type: mimeType }) }

base64からBlobへの変換

export const base64ToBlob = (base64: string, mimeType: string): Blob => { const byteCharacters = atob(base64.split(",")[1]) const byteNumbers = Array.from(byteCharacters, (char) => char.charCodeAt(0)) const byteArray = new Uint8Array(byteNumbers) return new Blob([byteArray], { type: mimeType }) }

base64からArrayBufferへの変換

経験上、base64からArrayBufferへの変換を行う機会はあまりないでしょう。したがって、新たに関数を作るよりは他で紹介した関数を用いて変換するのが良いでしょう。Blobを一度経由します。

export const base64ToArrayBuffer = (base64: string, mimeType: string) => { return fileToArrayBuffer(base64ToBlob(base64, mimeType)) }

番外編: URL.createObjectURLで作成したURLを相互変換

画像をこねるサービスを作っているとURL.createObjectURLも使うかもしれません。
これはブラウザが閉じたり、故意に開放するまでメモリ上にファイルを保持する機能です。
ブラウザ上に画像を表示するときなどに使います。

FileやBlobからObjectURLを作成する

これはmdnに書いてある通りにできます。

URL.createObjectURL(object)

ObjectURLからBlobへ変換する

fetchを使ってURLからファイルをダウンロードした後に変換して使えます。

export const objectURLToBlob = async (objectURL: string) => { const respnse = await fetch(objectURL) const blob = await respnse.blob() return blob }
yosi

Noh を作ってるエンジニア。