fileupload.worker.ts 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. /*
  2. * Copyright 2023 Avaiga Private Limited
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
  5. * the License. You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
  10. * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
  11. * specific language governing permissions and limitations under the License.
  12. */
  13. import { FileUploadData, FileUploadReturn } from "./fileupload.utils";
  14. const uploadFile = (
  15. blobOrFile: Blob,
  16. uploadUrl: string,
  17. varName: string,
  18. part: number,
  19. total: number,
  20. fileName: string,
  21. multiple: boolean,
  22. id: string,
  23. progressCb: (uploaded: number) => void
  24. ) => {
  25. const xhr = new XMLHttpRequest();
  26. xhr.open("POST", `${uploadUrl}?client_id=${id}`, false);
  27. xhr.onerror = (e) => self.postMessage({ message: "Error: " + e, error: true });
  28. xhr.onload = (e) => progressCb(e.lengthComputable ? e.loaded : 0);
  29. const fdata = new FormData();
  30. fdata.append("blob", blobOrFile, fileName);
  31. fdata.append("part", part.toString());
  32. fdata.append("total", total.toString());
  33. fdata.append("var_name", varName);
  34. fdata.append("multiple", multiple ? "True" : "False");
  35. xhr.send(fdata);
  36. };
  37. // 1MB chunk sizes.
  38. const BYTES_PER_CHUNK = 1024 * 1024;
  39. const getProgressCallback = (globalSize: number, offset: number) => (uploaded: number) =>
  40. self.postMessage({
  41. progress: ((offset + uploaded) * 100) / globalSize,
  42. done: false,
  43. } as FileUploadReturn);
  44. const process = (files: FileList, uploadUrl: string, varName: string, id: string) => {
  45. if (files) {
  46. let globalSize = 0;
  47. for (let i = 0; i < files.length; i++) {
  48. globalSize += files[i].size;
  49. }
  50. const uploadedFiles = [];
  51. for (let i = 0; i < files.length; i++) {
  52. const blob = files[i];
  53. const size = blob.size;
  54. let start = 0;
  55. let end = BYTES_PER_CHUNK;
  56. const tot = Math.ceil(size / BYTES_PER_CHUNK);
  57. while (start < size) {
  58. const chunk = blob.slice(start, end);
  59. const progressCallback = getProgressCallback(globalSize, start);
  60. progressCallback(0);
  61. uploadFile(
  62. chunk,
  63. uploadUrl,
  64. varName,
  65. Math.floor(start / BYTES_PER_CHUNK),
  66. tot,
  67. blob.name,
  68. i == 0 ? false : files.length > 0,
  69. id,
  70. progressCallback
  71. );
  72. progressCallback(chunk.size);
  73. start = end;
  74. end = start + BYTES_PER_CHUNK;
  75. uploadedFiles.push(blob.name);
  76. }
  77. }
  78. self.postMessage({
  79. progress: 100,
  80. message: uploadedFiles.join(", ") + " Uploaded Successfully",
  81. done: true,
  82. } as FileUploadReturn);
  83. }
  84. };
  85. self.onmessage = (e: MessageEvent<FileUploadData>) => {
  86. process(e.data.files, e.data.uploadUrl, e.data.varName, e.data.id);
  87. };