Blob を File にする
- カテゴリ:
- JavaScript
- コメント数:
- Comments: 0
◆ new File([blob], name, option) で Blob を File にできる
◆ コピーになるから大きいファイルの場合に注意
◆ コピーになるから大きいファイルの場合に注意
Blob → File
File は Blob を継承していて name とかプロパティが増えたくらいですなので単純に name プロパティつければ行けるんじゃない? と思ったのですが
async function main() {
const bin = Uint8Array.from([10, 20, 30, 40, 50])
const blob = new Blob([bin], { type: "application/octet-stream" })
blob.name = "file1.bin"
const fd = new FormData()
fd.append("blob-file", blob)
fd.append("message", "123")
fetch("http://localhost/", { method: "POST", body: fd })
}
main()
これのリクエストを見ると
------WebKitFormBoundaryWJK7SxWOvPvAHbAo
Content-Disposition: form-data; name="blob-file"; filename="blob"
Content-Type: application/octet-stream
略
filename は blob になってます
file1.bin という名前は使われてません
プロパティの有無じゃなくてちゃんと型で判断してそうです
なので ちゃんと Blob を File 型に変換します
async function main() {
const bin = Uint8Array.from([10, 20, 30, 40, 50])
const blob = new Blob([bin], { type: "application/octet-stream" })
const file = new File([blob], "file1.bin", { type: "application/octet-stream" })
const fd = new FormData()
fd.append("blob-file", file)
fd.append("message", "123")
fetch("http://localhost/", { method: "POST", body: fd })
}
main()
------WebKitFormBoundarywujHcsyP3u9Yi6n8
Content-Disposition: form-data; name="blob-file"; filename="file1.bin"
Content-Type: application/octet-stream
略
ちゃんと file1.bin が設定されました
コピーされる
Blob や File の 1 つ目の引数は ArrayBuffer や Blob の配列を入れるとそのデータがコピーされますread して Uint8Array で確認するとちゃんと同じものになってます
const blob2u8 = b => {
return new Promise(resolve => {
const r = new FileReader()
r.onload = () => resolve(new Uint8Array(r.result))
r.readAsArrayBuffer(b)
})
}
const blob = new Blob([Uint8Array.from([10, 20, 30])], {})
const file = new File([blob], "", {})
console.log(await blob2u8(blob))
// Uint8Array(3) [10, 20, 30]
console.log(await blob2u8(file))
// Uint8Array(3) [10, 20, 30]
Blob や File はコンストラクタで作成時にコピーされて変更不可のオブジェクトです
元になった ArrayBuffer を変えても Blob や File に影響はしませんが コピーが発生する以上 大きめのファイルなら注意したほうがいいかもです
使いみち
どういうシーンでタイミングで Blob から File に変換する必要があるのか ですがダウンロードしたファイルを POST するときなどに発生しますローカルファイルなら最初から File で取得できますが
const blob = await fetch(url).then(e => e.blob())
こういう fetch で取得するデータは Blob にしかなりません
POST するときにファイル名を含めたいなら Blob じゃなくて File にしないといけません
追記
FormData を使うなら 3 つ目の引数に filename を設定できましたconst bin = Uint8Array.from([10, 20, 30, 40, 50])
const blob = new Blob([bin], { type: "application/octet-stream" })
const fd = new FormData()
fd.append("blob-file", blob, "file1.bin")
fetch("http://localhost/", { method: "POST", body: fd })
------WebKitFormBoundary9GZPDvAB32SvqzEK
Content-Disposition: form-data; name="blob-file"; filename="file1.bin"
Content-Type: application/octet-stream
略
他に File 型である必要のあるところない思いつきませんし Blob から File への変換自体不要かもしれませんね