ディープアトランティックストレージWebブラウザでのファイルアップロードの読み込み
18283 ワード
This post is originally published on yoursunny.com blog https://yoursunny.com/t/2021/das-file-worker/
私は7月4日の休暇で退屈しているので、私は気まぐれなウェブページを作りました:Deep Atlantic Storage .
それは無料のファイルストレージサービスとして記述され、そこでは、任意のファイルをアップロードすることができます大西洋に深く、サイズ制限とコンテンツの制限なしで格納されます.
どのように、それはどのように私はそれを提供する余裕がありますか?
この記事は、大西洋のストレージの背後にある秘密を明らかに3部シリーズの2番目です.
The previous part すべてのビットをAにソートするアルゴリズムを導入しました
Uint8Array
.現在、私はそこから続きます、そして、ウェブページがどのようにファイルアップロードを受け入れて、処理するかについて説明してください.
ファイルアップロード
私が覚えている限り、ファイルアップロードは常にHTML標準の一部でした.
<form action="upload.php" method="POST" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit" value="upload">
</form>
これは、ユーザーがローカルファイルを選択できるようにするボタンを作成します.フォームが送信されると、ファイル名と内容がサーバーに送信され、サーバー側スクリプトがprocess the upload .
それは簡単ですが、深い大西洋のストレージに最適ではありません.
最後の記事で説明したように、ファイルがどれくらい大きいかに関係なく、すべてのビットをソートする結果は、ちょうど2つの数
0
ビットと1
ビットがファイルにあります.ファイル全体をサーバに送る必要はありません代わりに、ブラウザでカウントをはるかに高速になります.
ファイルとblob
2021年まで早送り、JavaScriptはすべてを行うことができます.
JavaScriptでは、
<input type="file">
要素は、(最初)選択したファイルにアクセスすることができます.files[0]
プロパティ.Using files from web applications これらのAPIの更なる説明があります.
.files[0]
aを返すFile
のサブクラスです.Blob
.Then, Blob.prototype.arrayBuffer() 関数はファイル全体を
ArrayBuffer
, コンテンツへのアクセスを提供する.<form id="demo_form">
<input id="demo_upload" type="file" required>
<input type="submit">
</form>
<script>
document.querySelector("#demo_form").addEventListener("submit", async (evt) => {
evt.preventDefault();
const file = document.querySelector("#demo_upload").files[0];
console.log(`file size ${file.size} bytes`);
const payload = new Uint8Array(await file.arrayBuffer());
const [cnt0, cnt1] = countBits(payload); // from the previous article
console.log(`file has ${cnt0} zeros and ${cnt1} ones`);
});
</script>
このコードはイベントリスナーを<form>
.フォームが送信されると、コールバック関数はファイルを
ArrayBuffer
そして、Uint8Array
ビットカウント機能countBits
前記事より)readablestream
file.arrayBuffer()
作品が、問題がある:ユーザーが巨大なファイルを選択した場合、ファイル全体が一度にメモリに読み込まれる必要があります、かなりのメモリストレスを引き起こす.この問題を解決するためにStreams API 小さいチャンクでファイルを読み込み、各チャンクを処理する前に次の文字を読み込みます.
から
Blob
オブジェクトfile
上記のスニペットでは、コールできます .stream().getReader()
作成するReadableStreamDefaultReader
.そして、私は繰り返し呼び出すことができます
reader.read()
, これは、データのチャンクかファイル終端(EOF)指示のどちらかに解決する見込みを返します.チャンクによってファイルチャンクを処理し
1
ビットがあります、私の戦略はそうです:reader.read()
ループで、次のチャンクを取得します.done
が真で、EOFが到達したことを示すと、ループを中断します.1
チャンクの各バイトのビットは、全体のカウンタになります.0
ビットはファイルサイズから、アクセス可能ですblob.size
プロパティ.async function countBitsBlob(blob: Blob): Promise<[cnt0: number, cnt1: number]> {
const reader = (blob.stream() as ReadableStream<Uint8Array>).getReader();
let cnt = 0;
while (true) {
const { done, value: chunk } = await reader.read();
if (done) {
break;
}
for (const b of chunk!) {
cnt += ONES[b];
}
}
return [8 * blob.size - cnt, cnt];
}
Webワーカー
Webアプリケーションでは、バックグラウンドスレッドで複雑な計算を実行するのが最善です.そのため、主スレッドがユーザー間の対話に迅速に対応できます.
Web Workers Webコンテンツの背景スレッドでスクリプトを実行するための簡単な手段です.
深い大西洋保管では、私はファイルのビットをソートするか、数える仕事をウェブ労働者に委任しました.
ユーザーがファイルを選択し、フォームを送信すると、フォームイベントハンドラーは
Worker
(もしそうしなければ)Worker.prototype.postMessage() 通るFile
バックグラウンドスレッドへのオブジェクト.let worker;
document.querySelector("#demo_form").addEventListener("submit", async (evt) => {
evt.preventDefault();
const file = document.querySelector("#demo_upload").files[0];
worker ??= new Worker("worker.js");
worker.onmessage = handleWorkerMessage; // described later
worker.postMessage(file);
});
The worker.js
バックグラウンドで実行します.メッセージを受信するMessageEvent エンクロージャ
File
グローバルに割り当てられた関数onmessage
変数.この関数は
countBitsBlob
ゼロとファイルの数をカウントするにはpostMessage 関数は、結果をWebページのメインスレッドに渡します.また、スローされた可能性のあるエラーをキャッチし、メインスレッドにも渡す.
含まれている
type: "result"
and type: "error"
これらの2種類のメッセージでは、メインスレッドがそれらを区別できるようにします.onmessage = async (evt) => {
const file = evt.data;
try {
const result = await countBitsBlob(file);
postMessage({ type: "result", result });
} catch (err) {
postMessage({ type: "error", error: `${err}` });
}
};
注意してくださいcatch
条項Error
オブジェクトは、postMessage
.これは必要なのはa handful of types 通ることができる
postMessage
, でもError
それらの1つではない.メインスレッドに戻る
handleWorkerMessage
に割り当てられたworker.onmessage
プロパティは、ワーカースレッドからメッセージを受け取ります.function handleWorkerMessage(evt) {
const response = evt.data;
switch (response.type) {
case "result": {
const [cnt0, cnt1] = response.result;
console.log(`file has ${cnt0} zeros and ${cnt1} ones`);
break;
}
case "error": {
console.error("worker error", response.error);
break;
}
}
}
いくつかのユーザーインターフェイスの魔法(この記事では説明されていないが、Webページのソースコードを見ることができます)と組み合わせることで、これはディープ大西洋ストレージWebページを構成します.概要
この記事は、後ろの秘密を明らかにする3部シリーズの第2ですDeep Atlantic Storage .
ビットカウントアルゴリズムの設計previous article , 私はストリームAPI経由でチャンクでアップロードされたファイルのチャンクを読み取り、Webワーカーを介してバックグラウンドスレッドに重いリフティングを移動するWebアプリケーションにそれを回した.
The next part このシリーズでは、どのように私はビットカウントからファイルを再構築するサーバーを作った説明します.
Reference
この問題について(ディープアトランティックストレージWebブラウザでのファイルアップロードの読み込み), 我々は、より多くの情報をここで見つけました https://dev.to/yoursunny/deep-atlantic-storage-reading-file-upload-in-web-workers-1hj6テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol