딥 애틀랜틱 스토리지: 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.)