fileupload.worker.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /*
  2. * Copyright 2021-2024 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. context: string | undefined,
  19. onAction: string | undefined,
  20. uploadData: string | undefined,
  21. part: number,
  22. total: number,
  23. fileName: string,
  24. multiple: boolean,
  25. id: string,
  26. progressCb: (uploaded: number) => void
  27. ) => {
  28. const xhr = new XMLHttpRequest();
  29. xhr.open("POST", `${uploadUrl}?client_id=${id}`, false);
  30. xhr.onerror = (e) => self.postMessage({ message: "Error: " + e, error: true });
  31. xhr.onload = (e) => progressCb(e.lengthComputable ? e.loaded : 0);
  32. const fdata = new FormData();
  33. fdata.append("blob", blobOrFile, fileName);
  34. fdata.append("part", part.toString());
  35. fdata.append("total", total.toString());
  36. fdata.append("var_name", varName);
  37. context && fdata.append("context", context);
  38. onAction && fdata.append("on_action", onAction);
  39. uploadData && fdata.append("upload_data", uploadData);
  40. fdata.append("multiple", multiple ? "True" : "False");
  41. xhr.send(fdata);
  42. };
  43. // 1MB chunk sizes.
  44. const BYTES_PER_CHUNK = 1024 * 1024;
  45. const getProgressCallback = (globalSize: number, offset: number) => (uploaded: number) =>
  46. self.postMessage({
  47. progress: ((offset + uploaded) * 100) / globalSize,
  48. done: false,
  49. } as FileUploadReturn);
  50. const process = (
  51. files: FileList,
  52. uploadUrl: string,
  53. varName: string,
  54. context: string | undefined,
  55. onAction: string | undefined,
  56. uploadData: string | undefined,
  57. id: string
  58. ) => {
  59. if (files) {
  60. let globalSize = 0;
  61. for (let i = 0; i < files.length; i++) {
  62. globalSize += files[i].size;
  63. }
  64. const uploadedFiles = [];
  65. for (let i = 0; i < files.length; i++) {
  66. const blob = files[i];
  67. const size = blob.size;
  68. let start = 0;
  69. let end = BYTES_PER_CHUNK;
  70. const tot = Math.ceil(size / BYTES_PER_CHUNK);
  71. while (start < size) {
  72. const chunk = blob.slice(start, end);
  73. const progressCallback = getProgressCallback(globalSize, start);
  74. progressCallback(0);
  75. uploadFile(
  76. chunk,
  77. uploadUrl,
  78. varName,
  79. context,
  80. onAction,
  81. uploadData,
  82. Math.floor(start / BYTES_PER_CHUNK),
  83. tot,
  84. blob.name,
  85. i == 0 ? false : files.length > 0,
  86. id,
  87. progressCallback
  88. );
  89. progressCallback(chunk.size);
  90. start = end;
  91. end = start + BYTES_PER_CHUNK;
  92. }
  93. uploadedFiles.push(blob.name);
  94. }
  95. self.postMessage({
  96. progress: 100,
  97. message: uploadedFiles.join(", ") + " Uploaded Successfully",
  98. done: true,
  99. } as FileUploadReturn);
  100. }
  101. };
  102. self.onmessage = (e: MessageEvent<FileUploadData>) => {
  103. process(e.data.files, e.data.uploadUrl, e.data.varName, e.data.context, e.data.onAction, e.data.uploadData, e.data.id);
  104. };