Skip to content

Instantly share code, notes, and snippets.

@mindon
Created May 7, 2023 17:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mindon/ccbf3724987f4a7478138e3fb3facda6 to your computer and use it in GitHub Desktop.
Save mindon/ccbf3724987f4a7478138e3fb3facda6 to your computer and use it in GitHub Desktop.
fetch large file with progress callback
async function get$(src, cb, opts = { method: "GET" }) {
let [current, received, total] = [0, 0, 0];
cb({ state: "nif" });
const resp = await fetch(src, {
mode: "cors",
headers: {
"Content-Type": "application/octet-stream",
},
...(opts || {}),
}).catch((error) => cb({ error, code: resp.status }));
if (!resp.ok) {
cb({ error: resp.statusText, code: resp.status });
return;
}
total = parseInt(resp.headers.get("content-length"), 10);
const reader = resp.body.getReader();
const chunks = [];
let last = -1;
cb({ current, received, total });
while (true) {
const { done, value } = await reader.read();
if (done || !total) {
break;
}
chunks.push(value);
received += value.length;
if (total) {
current = Math.round(1000 * received / total) / 10.0;
cb({ received, total, current, value });
if (current != last) {
last = current;
}
}
}
let position = 0;
const chunksAll = new Uint8Array(received);
for (const chunk of chunks) {
chunksAll.set(chunk, position);
position += chunk.length;
}
cb({ state: "fin", total, body: chunksAll });
return chunksAll;
}
// get$(
// "http://localhost/a-very-large-file",
// (
// {
// state = "",
// error = "",
// received = 0,
// total = 0,
// current = 0,
// value = "",
// },
// ) => {
// console.log(state, error, current, received, total, value.length);
// },
// );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment