딥 애틀랜틱 스토리지: Web Workers에서 파일을 읽고 업로드
18339 단어 webworkerjavascript
This post is originally published on yoursunny.com blog https://yoursunny.com/t/2021/das-file-worker/
7월 4일 방학에 나는 매우 심심해서 이상한 웹 페이지를 만들었다. Deep Atlantic Storage.
그것은 대서양 깊숙한 곳에 파일을 올릴 수 있는 무료 파일 저장 서비스로 묘사되어 있으며, 크기 제한과 내용 제한이 없다.
그것은 어떻게 일을 하는지, 내가 또 어떻게 감당할 수 있겠는가?
본고는 세 부분으로 구성된 시리즈의 두 번째 부분으로 이 시리즈는 심대서양 저장소의 배후 비밀을 밝히고 있다.
previous part은
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이 될 수 있습니다.
이것은 매우 간단하지만 대서양 깊은 곳의 저장에 있어서는 결코 이상적이지 않다.
이전 글에서 설명한 바와 같이 파일이 아무리 크더라도 모든 위치를 정렬한 결과는 두 가지 숫자로 표시할 수 있다. 파일에 얼마나 많은
0위와 1위인지.전체 파일을 서버에 보낼 필요가 없습니다.반대로 브라우저에서는 계수가 훨씬 빨라진다.
파일 및 스펙클
2021년이 다가오면 자바스크립트는 무엇이든 할 수 있다.
JavaScript에서
<input type="file"> 요소에 대응하는 DOM 대상을 지정하면 .files[0] 속성을 통해 선택한 파일에 접근할 수 있습니다.Using files from web applications은 이러한 API에 대해 더 자세히 설명합니다.
.files[0]은 File의 대상을 되돌려주고 이 대상은 Blob의 하위류이다.그리고 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).가독성 흐름
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 Workers은 웹 콘텐츠를 백엔드 라인에서 스크립트를 실행하는 간단한 방법이다.
Deep Atlantic Storage에서 나는 파일의 정렬이나 계수 작업을 인터넷 작업자에게 의뢰했다.

사용자가 파일을 선택하고 폼을 제출할 때, 폼 이벤트 처리 프로그램은
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);
});
worker.js은 백그라운드에서 작동합니다.이것은 전역 변수
File에 분배된 함수에서 메시지를 수신한다(MessageEvent은 onmessage 대상을 포함한다).그 다음에 이 함수는
countBitsBlob을 호출하여 파일에 몇 개의 0과 1이 있는지 계산한 다음에 전역 postMessage 함수를 호출하여 결과를 웹 페이지의 메인 라인으로 전달한다.그것 또한 던질 수 있는 모든 오류를 포착하여 주 라인에 전달한다.
나는 이 두 가지 메시지에
type: "result"과 type: "error"을 포함하여 주 라인이 그것들을 구분할 수 있도록 했다.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은 그 중의 하나가 아니기 때문이다.주 라인으로 돌아가서
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;
}
}
}
게다가 일부 사용자 인터페이스 마법(본문에는 설명이 없지만 웹 소스 코드를 볼 수 있음)을 더하면 Deep Atlantic Storage 웹 페이지를 구성할 수 있다.요약
본고는 Deep Atlantic Storage의 배후 비밀을 밝히는 세 부분 시리즈의 두 번째 부분이다.
previous article에서 디자인한 비트계수 알고리즘을 토대로 저는 이를 웹 응용 프로그램으로 전환시켜Streams API를 통해 업로드된 파일을 블록별로 읽고 웹워커스를 통해 복잡한 작업을 백엔드 라인으로 옮깁니다.
이 시리즈의 next part은 비트 계수에 따라 파일을 재구성하기 위해 서버를 만드는 방법을 설명할 것입니다.
Reference
이 문제에 관하여(딥 애틀랜틱 스토리지: Web Workers에서 파일을 읽고 업로드), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/yoursunny/deep-atlantic-storage-reading-file-upload-in-web-workers-1hj6텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)