async webtransport file upload progress bar serial 2

by jib1

HTML

<script src="https://jan-ivar.github.io/polyfills/streamiterator.js"></script>
<script src="https://jan-ivar.github.io/dummy/progressbar.js"></script>
<script src="https://jan-ivar.github.io/polyfills/unidirectionalstreams.js"></script>
<script src="https://jan-ivar.github.io/polyfills/createstreamofunidirectionalstreams.js"></script>
Select several <input type="file" id="browse" multiple><br>
<div id="container"></div><br><div id="div2"></div>
<div id="div"></div>

JavaScript

const console = {log: msg => div.innerHTML += `${msg}<br>`,
                  error: e => console.log(`${e.name}: ${e.message}`)};

(async url => {
  try {
    const transport = new WebTransport(url);
    const streams = new TransformStream();
    const streamsWriter = streams.writable.getWriter();
    const chunkSize = 16*1024;

    browse.onchange = async () => {
      try {
        for (const file of browse.files) {
          console.log(`Sending ${file.name} (${file.size} bytes)...`);

          const bar = makeProgressBar(file);
          const stream = makeReadableFileStream(file, chunkSize, bar);
          streamsWriter.write(stream).catch(() => {});
        }
      } catch (e) {
        console.error(e);
      }
    };
    await streams.readable
      .pipeThrough({writable: transport.createStreamOfUnidirectionalStreams(),
                    readable: transport.unidirectionalStreams.readable})
      .pipeTo(new WritableMessageStreamsConsole("From server: "));

  } catch (e) {
    console.error(e);
  }
})("https://webrtc.internaut.com:6161/echo");

function makeReadableFileStream(file, chunkSize, bar) {
  const ms = performance.now();
  let position = 0;
  return new ReadableStream({
    async pull(controller) {
      const size = Math.min(file.size - position, chunkSize);
      if (!size) {
        console.log(`${((performance.now() - ms) / 1000).toFixed(2)} seconds`);
        return controller.close();
      }
      const blob = file.slice(position, position + size, file.type);
      controller.enqueue(await blobToArrayBuffer(blob));
      position += size;
      bar && bar.progress(position);
    },
  });
}

async function blobToArrayBuffer(blob) {
  const reader = new FileReader();
  reader.readAsArrayBuffer(blob);
  await new Promise(r => reader.onload = r);
  return reader.result;
}

function WritableConsole(header = "") {
  return new WritableStream({
    write: msg => console.log(`${header}${msg}`),
    close: () => console.log(`${header}👋`),
   ...