async function ChunkedUploadFromEntry()

in frontend/app/DeliverableUploader/UploadService.ts [58:150]


async function ChunkedUploadFromEntry(
  entry: FileEntry,
  index: number,
  uploadSlotId: string,
  chunkSize: number,
  updateCb: (updated: FileEntry, index: number) => void
) {
  const uploadChunk = async (chunkIndex: number) => {
    const lastByte =
      (chunkIndex + 1) * chunkSize > entry.rawFile.size
        ? entry.rawFile.size
        : (chunkIndex + 1) * chunkSize;
    const blob = entry.rawFile.slice(chunkIndex * chunkSize, lastByte);
    let localEntry = Object.assign([], entry);
    let response: Response;
    const targetUrl = `/deliverable-receiver/upload?uploadId=${uploadSlotId}&fileName=${entry.filename}`;

    try {
      const token = localStorage.getItem("pluto:access-token");
      response = await fetch(targetUrl, {
        method: "POST",
        headers: {
          "Content-Type": "application/octet-stream",
          Authorization: `Bearer ${token}`,
          Range: `bytes=${chunkIndex * chunkSize}-${lastByte}/${
            entry.rawFile.size
          }`,
        },
        body: blob,
      });
    } catch (err) {
      console.error("Upload failed: ", err);
      localEntry.lastError = err.toString();
      updateCb(localEntry, index);
      throw "upload failed";
    }

    switch (response.status) {
      case 413:
        localEntry.lastError = "chunk size is too large";
        updateCb(localEntry, index);
        throw "upload failed";
      case 500 | 400:
        try {
          const responseBody = await response.json();
          if (responseBody.detail) {
            localEntry.lastError = responseBody.detail;
          } else {
            localEntry.lastError = responseBody.toString();
          }
          updateCb(localEntry, index);
        } catch (err) {
          console.warn("could not parse error json: ", err);
          localEntry.lastError = "server error, see browser console";
          updateCb(localEntry, index);
        }
        throw "upload failed";
      case 503:
        localEntry.lastError = "server not responding, retrying...";
        updateCb(localEntry, index);
        return new Promise((resolve, reject) =>
          window.setTimeout(() => {
            uploadChunk(chunkIndex)
              .then(resolve)
              .catch((err) => reject(err));
          }, 2000)
        );
      case 403:
        localEntry.lastError = "permission denied";
        updateCb(localEntry, index);
        throw "upload failed";
      case 200:
        const responseBody = await response.json();
        console.log(responseBody);
        const fractionComplete =
          ((chunkIndex + 1) * chunkSize) / entry.rawFile.size;
        localEntry.progress = Math.round(fractionComplete * 100.0);
        updateCb(localEntry, index);
    }
  };

  const chunksCount = Math.ceil(entry.rawFile.size / chunkSize);
  console.log(
    "chunked upload: there are ",
    chunksCount,
    " chunks for file of size ",
    entry.rawFile.size
  );
  for (let i = 0; i < chunksCount; i++) {
    console.log("uploading chunk ", i);
    await uploadChunk(i);
  }
}