![見出し画像](https://assets.st-note.com/production/uploads/images/123556744/rectangle_large_type_2_e42b027229961b60e8b6c29d32e11f4a.png?width=1200)
JavaScript 巨大なローカルファイルの部分的な読み込み
<input type="file">で選択したローカルファイルの部分アクセス方法
※OS、ブラウザによっては使えない可能性があります
Fileインターフェイスのslice
<input>で選択した時点では、ファイルは読み込まれません。
FileはBlobの機能を備えています。slice関数を使用すれば、ローカルファイルへの部分アクセスが可能です。
// File ローカルファイルの部分アクセス
let blob = file.slice(0, 1024*1024);
let abuff = await blob.arrayBuffer();
動作確認
メモリ使用量の確認
Windows11 : Chrome / Edge
Windows10 : Edge / FireFox
※OS、ブラウザによって動作が異なる可能性あり
iPad iPhoneなどiOS系は選択した時点ですべて読み込まれているよう挙動でした(推測です 大きな動画ファイルを読み込むと失敗)。
メモリスナップショット(Edge)
![](https://assets.st-note.com/img/1701669269911-Y3E032smkr.png?width=1200)
![](https://assets.st-note.com/img/1701669300568-0pPagwR4Zc.png?width=1200)
![](https://assets.st-note.com/img/1701669339684-l3HV110XMn.png?width=1200)
確認用ソースコード
export async function main(){
let ifile = <HTMLInputElement>document.getElementById("file");
let signal = new SignalWait<File>();
ifile.oninput = ()=>{
if(ifile.files && ifile.files[0]){
signal.signal(ifile.files[0]);
}
}
let file = await signal.wait();
console.log(file);
//この時点ではファイルは読み込まれない
// ※ Windows : Edge/FireFox の場合
// OSやブラウザによって挙動が変わる可能性があります
// 全て読み込んだ場合
let buff = await file.arrayBuffer();
// メモリ使用量がファイルサイズ分増加
// 部分的な読み込み
file = await signal.wait();
buff = await file.slice(0, 1024*1024).arrayBuffer();
// 読み込んだ分だけ使用メモリ増加
// 連続した部分的な読み込み 解析処理とか
file = await signal.wait();
let step = 4*1024*1024;
for(let i=0;i<file.size/2;i+=step){
buff = await file.slice(i,i+step).arrayBuffer();
// 使い終わったら削除
console.log(buff.byteLength)
}
// メモリ使用量の累積なし 読み込んだ分だけ使用メモリ増加
file = await signal.wait();
// File ローカルファイルの部分アクセス
let blob = file.slice(0, 1024*1024);
let abuff = await blob.arrayBuffer();
}
export class SignalWait<T=any>{
resolve : any[];
constructor(){
this.resolve = [];
}
async wait() : Promise<T>{
return new Promise((rs)=>{this.resolve.push(rs);});
}
signal(val : T){
if(this.resolve !== undefined){
for(let rs of this.resolve){
rs(val);
}
this.resolve = [];
}
}
}
いいなと思ったら応援しよう!
![zerogram](https://assets.st-note.com/production/uploads/images/79406964/profile_52d439edf0ed5fbf453ca56d5f22a6d9.png?width=600&crop=1:1,smart)