Uploading files in JavaScript can cause browser lag due to chunk uploading

While attempting to upload a file by chunking it and sending it to the server, I am encountering an issue with this code. Currently, I am only chunking the file without processing the chunks further. The main problem arises when the file size is 2GB; if the chunkCount exceeds 1000, it leads to multiple requests that can potentially DDOS the server. On the other hand, if the chunkCount is under 100, the client experiences significant lag.

So why not upload the file normally instead of handling it in chunks? Chunking allows for pausing the uploading process, and if any chunk triggers a connection issue, you can retry from that specific chunk onwards.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Video Thumbnail Generator</title>
    <link
      href="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f793969e848e829eb7c3d9c6c5d9c6c7">[email protected]</a>/dist/full.min.css"
      rel="stylesheet"
      type="text/css"
    />
    <script src="https://cdn.tailwindcss.com"></script>
  </head>
  <body>
    <span class="loading loading-spinner loading-lg"></span>
    <h1>File Chunk Processor</h1>
    <input type="file" id="fileInput" />

    <button id="processButton" onclick="DoChunk()">Process File</button>

    <script>
      function DoChunk() {
        
        let chunkCount = 1700;
        let chunkIndex = 0;
        processNextChunk(chunkIndex, chunkCount);
      }

      function processNextChunk(chunkIndex, chunkCount) {
        if (chunkIndex < chunkCount) {
          processFileChunk('fileInput', chunkIndex, chunkCount, function () {
            setTimeout(() => {
              processNextChunk(chunkIndex + 1, chunkCount);
            }, 100); // Adjust the delay as needed
          });
        }
      }

      function processFileChunk(elementId, chunkIndex, chunkCount, callback) {
        // Get the file input element
        const inputElement = document.getElementById(elementId);

        // Check if the input element and file are available
        if (!inputElement || !inputElement.files || !inputElement.files[0]) {
          console.error('No file selected or element not found');
          return;
        }

        // Get the selected file
        const file = inputElement.files[0];

        // Calculate the size of each chunk
        const chunkSize = Math.ceil(file.size / chunkCount);
        const start = chunkIndex * chunkSize;
        const end = Math.min(start + chunkSize, file.size);

        // Create a Blob for the specific chunk
        const chunk = file.slice(start, end);

        // Create a FileReader to read the chunk
        const reader = new FileReader();

        reader.onload = function (event) {
          // Get the chunk content as a Base64 string
          const base64String = event.target.result.split(',')[1]; // Remove data URL part

          // Output or process the chunk as needed
          console.log(`Chunk ${chunkIndex + 1} of ${chunkCount}:`);
          console.log(base64String);

          if (callback) {
            callback();
          }
        };

        reader.onerror = function (error) {
          console.error('Error reading file chunk:', error);
          if (callback) {
            callback();
          }
        };

        // Read the chunk as a Data URL (Base64 string)
        reader.readAsDataURL(chunk);
      }
    </script>
  </body>
</html>

Additionally, here is my API code written in ASP.NET that accepts and processes chunks as strings, where each string represents a long chunked base64 value.

 public async Task<IActionResult> UploadChunkAsync([FromBody] FileChunkRequest request,
        CancellationToken cancellationToken = default)
    {
        var requestToken = _jwtTokenRepository.GetJwtToken();
        var loggedInUser = _jwtTokenRepository.ExtractUserDataFromToken(requestToken);

        var blobTableClient = _blobClientFactory.BlobTableClient(TableName.StashChunkDetail);

        var stashChunkDetail = blobTableClient
            .Query<StashChunkDetail>(x => x.RowKey == request.UploadToken && x.UserId == loggedInUser.id)
            .SingleOrDefault();

        ...
        [API code continues here]
        ...

            return StatusCode(StatusCodes.Status201Created, responseChunkProgress);
        }

        return BadRequest("Please Request New Upload Token");
    }

Answer №1

To prevent overloading your server, it is recommended to wait for each request to complete before moving on to the next portion of the file. The code snippet below demonstrates this concept, sending each chunk to :

function sendChunk(file, start) {
  if (start < file.size) {
    var reader = new FileReader();
    reader.onload = async function(event) {
      console.log(
        (
          await (
            await fetch("https://httpbin.org/anything", {
              method: "POST",
              body: reader.result
            })
          ).json()
        ).data
      );
      sendChunk(file, start + 128);
    };
    reader.readAsArrayBuffer(file.slice(start, start + 128));
  }
}
<input id="file" type="file" />
<button onclick="sendChunk(file.files[0], 0)">Send Chunk</button>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Replace each occurrence of a specific "tag" (as a string) with all the corresponding matches in JavaScript

I need help with permuting a string in different ways to explore all possible values. Initially, I have an object structured like this: { descriptions: ["Here's some <tag> example", "Can be something without Tag"], headlines: ["<tag> ...

implementing a like button next to every item on a list using ajax

Help needed: How can I add a like button next to each item on my 'destinations' list? I'm struggling to figure out the placement. Any suggestions? Below is the content of my dashboard.html.erb file: <div class="destination-list"> ...

Successfully submitting form_with without experiencing any errors for mandatory fields

I am currently dealing with a form that triggers a sidekiq worker upon submission. The issue I am facing is that even if the form is empty, clicking submit still attempts to run the worker. What I would like is for an alert to notify the user that the fiel ...

Trigger animation when the scroll position reaches 0.52 in Next.js using framer-motion

I’m working on a landing page and I have a section where I’d like to create a simple opacity animation using framer-motion. The issue is that these animations typically trigger as soon as you land on the page, but I want them to be based on scroll pos ...

Designing a Dynamic Floating Element that Shifts with Scroll Movement

Hey there everyone!, I am currently working on a project in Wordpress and I was wondering if anyone has experience creating a floating widget that moves along with the page as you scroll. Any suggestions on how to achieve this? Would it involve using Javas ...

Request a HTML variable and send it to JavaScript

My latest project involves a Binary to Decimal Calculator that is now fully functional, but I am looking to integrate an HTML input into it. <html> <input placeholder="00000000" name="htmlinput"></input> <input id="clickMe" type="butt ...

Deciding Between Promises and Callbacks in Node.js

As I update my older Node.js code, I am also creating new modules to integrate with the existing code. One challenge I face is transitioning from using callbacks to utilizing ES6 promises more frequently. This has created a mixture of functions that return ...

The font in my Next.js / Tailwind CSS project starts off bold, but unexpectedly switches back to its original style

I recently integrated the Raleway font into my minimalist Next.js application with Tailwind CSS. I downloaded the font family in .ttf format and converted it to .woff2, but I'm having trouble changing the font weight using custom classes like font-bol ...

Inquiring about the best method to determine the intersection point between two lines in Draw i.o

Can someone please explain how to find the coordinate point where two lines intersect in draw i.o? I am looking for a Javascript function to solve this issue and get the coordinate of the point only. For example: ...

ASP.Net Postback issue preventing retrieval of selected value

I am loading an ASP.Net Dropdown list by fetching values from an Ajax call Json Response with the following code. $.ajax({ type: "POST", url: "Default.aspx/SelectMoveToFund", data: JSON.stringify(params), c ...

Is there a way to avoid adding this final "faulty state" to the array?

While working on dynamically slicing an array, I noticed that my while loop was causing an extra slice to be added when it broke the conditional. Even though I can achieve the desired functionality by removing the last element with arr.pop(), I am curious ...

AngularJS and breaking the lines

I'm encountering a new issue. I have a straightforward form: <form ng-submit="funcion_modelo_adherir_cadena()"> <textarea ng-model="nuevo_modelo.scan_addresses" name="nuevo_modelo.scan_addresses" value="" ></textarea> <input type ...

Encountering a problem with deleting, inserting, or updating in ASP.NET, but the display functionality is

I used the wizard to generate Insert Edit Update and Delete statements. However, they are not functioning properly in my grid view. Every time I try to use them, I encounter the following error: No value provided for one or more required parameters. I am ...

Error: Attempting to split an undefined property (function without a name)

Trying to troubleshoot an error after moving a form that was functioning correctly on the index page to the post page. Unfortunately, simply relocating the form has resulted in an error: Uncaught TypeError: Cannot read property 'split' of undefin ...

Selenium htmlUnit with dynamic content failing to render properly

My current project involves creating Selenium tests for a particular website. Essentially, when a user navigates to the site, a CMS injects some dynamic elements (HTML + JS) onto the page. Everything works fine when running tests on the Firefox driver. H ...

execute javascript after successfully fetching data using ajax

index.php <script type="text/javascript"> $( document ).ready(function() { $('[data-countdown]').each(function() { var $this = $(this), finalDate = $(this).data('countdown'); $this.countdown(finalDate, function(e ...

Updating the initialState in your application while employing the useState function with React Hooks

I'm currently facing an issue with updating the image value in the local state. Everything works fine initially, but once I return to the same page, the initialState seems to retain the previous value. To resolve this, I find myself having to assign t ...

Blazor Server: Seamless breadcrumb navigation updates with JavaScript on all pages

I have implemented a breadcrumb feature in my Blazor Server project within the AppLayout that functions for all pages: <ul id="breadcrumbs" class="breadcrumbs"> <li><a href="#">Home</a></li> ...

Associate the callback function with a directive that does not have an isolated scope

Ensuring the correct context when binding a callback function to a directive is crucial. When working with an isolated scope, this task is easily accomplished. <bar-foo callback="mycontroller.callback()"></bar-foo> The directive code: ... ...

Tips for transferring an array from a form to a URL using JavaScript?

My form uses a get method, and includes a select element allowing users to choose multiple options. However, when the user submits the form, the URL does not neatly display these selections. Is there a way for me to pass the array in a more organized manne ...