JavaScript Looping through multiple files for upload will return the last file in the series

I'm currently working on implementing a multiple file upload feature using JavaScript.

Within my HTML, I have the following input:

 <input type="file" (change)="fileChange($event,showFileNames)" multiple />

When the onChange event is triggered, the following code is executed:

this.files = [].slice.call(event.target.files);
input.value = this.files;

The this.files array now contains the files to be uploaded.

Upon clicking "SUBMIT", I attempt to execute the following code snippet. This code was sourced from a previous thread's answer, but I haven't had success with it yet.

upload() {
    for (var i = 0; i < this.files.length; i++) { //for multiple files       
         var that = this;
         (function (file) {   
             var name = file.name;
             var reader = new FileReader();

             let parts = file.name.split(".");
             that.filename = parts[0];

             if (typeof (parts[1]) != "undefined")
                  that.ext = "." + parts[1];
             else
                  that.ext = "";

             reader.onload = function (e) {
                 var x = this.result;
                 let fileJSON = { "Filename": that.filename, "Extension": that.ext, "DateCreated": new Date(), "Data": btoa(this.result), "Sguid": that.tripsToEditx.sguid };
                 console.log(fileJSON);
             }
             reader.readAsArrayBuffer(file);
        })(this.files[i]);
    }
}

The variables name, ext, and tripsToEditx are global variables that couldn't be accessed using .this, so I used

var that = this;

Despite my efforts, I am still encountering the issue of the last selected file being printed three times. Any suggestions on how to resolve this?

Answer №1

When using btoa on an ArrayBuffer, it may not behave as you anticipate. However, btoa works perfectly fine on a Uint8Array. By creating a view of the ArrayBuffer, we can then proceed to use btoa on it.

For a demonstration, select some files and check the output in your browser's console.

Just FYI, there is no need for a function closure if you are comfortable using let and const, as these will handle things automatically for you.

function arrayBufferToHex(buffer) {
  const view  = new Uint8Array( buffer );
  return Array.prototype.map.call(view, function(byte) {
    return ('0' + (byte & 0xFF).toString(16)).slice(-2);
  }).join('');
}


document.querySelector("input").onchange = function () {  
  for (let i = 0; i < this.files.length; i++) {
    const file = this.files[i];
    const reader = new FileReader();
    reader.readAsArrayBuffer(file);
    reader.onloadend = function (e) {     
      const splits = file.name.split(".");
      const fileJSON = { 
        "Filename": splits[0], 
        "Extension": splits[1], 
        "DateCreated": new Date(), 
        "Data": arrayBufferToHex(this.result), 
        "Sguid": "XYZ" };
      console.log(fileJSON);
    }
  }
}
<div>Open browser console, to see results.</div>
<br>

<input type="file" multiple />

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

When publishing, TypeScript-compiled JS files fail to be included, even though they are included during the build process in Debug and Release modes

My .NET MAUI project includes TypeScript files in the Scripts\scriptfiles.ts folder, which are compiled into wwwroot\js\scriptfiles.js. Everything functions properly until my client attempts to publish it, at which point all script files go ...

Breaking apart a string and mapping it to specific fields

My issue is relatively straightforward. Upon loading my page, a long string representing an address is generated. For example: 101, Dalmations Avenue, Miami, Florida, USA, 908343 With the help of jQuery, I can split the string using: var address = sel.o ...

Express.js does not display console.log messages while routing

Just starting to explore Express and its middleware functions. var express = require('express'); var app = express(); app.get('/', function(req, res) { res.send('id: ' + req.params.id + ' and name: ' + req.param ...

Why does the playwright's onEnd() results not include the duration as specified in the documentation? What am I overlooking?

The built-in onEnd method can have a results object that is accessible within the function. According to the documentation here, this object should include the property duration, which represents the time in milliseconds. However, when I attempt to access ...

Autofill functions may not be compatible with input fields generated using JavaScript

Having trouble with browsers not using autocomplete in login overlays generated with JavaScript? It can be really annoying. Any suggestions on how to fix this issue? Should I create a hidden form within the original HTML and then move it into the overlay? ...

Apply Jquery to add emphasis to every item on the list

Can someone help me with this assignment? I need to create a jQuery function that italicizes all list elements on the page when triggered by the client. Here is my current approach: $(document).ready(function() { $("li").click(function() { ...

Animation loading on React.js when the page or URL is changed

Just starting out with React and trying to incorporate a loading animation when the page/url changes on button click - check it out here: https://codesandbox.io/s/cthululel-7zmsl?fontsize=14 Successfully got the animation working on initial load, but runn ...

What is the best way to create a sidebar that remains open without triggering a new sidebar every time it is clicked

I am looking to add a sidebar that opens a new view without navigating to a different page. The sidebar remains consistent and I want to avoid duplicating it on all pages. Check out this photo for an example. My goal is to provide additional content or fe ...

When the React Native Expo app is running, the TextInput form is covered by the keyboard

When I launch the app using expo and implement my DateFormInput component, the issue of Keyboard covering TextInput arises. Despite trying packages like "@pietile-native-kit/keyboard-aware-scrollview", "@types/react-native-keyboard-spacer", "react-native-k ...

Error: jwt_decode function has not been declared

I'm currently working on a project and I've hit a roadblock while trying to fetch profile information for the logged-in account using a token. Despite using the JWT-decoding library, I keep encountering the issue where jwt_decode is not defined. ...

What is the reason behind the automatic activation of a function when a nested React modal is

I've been experimenting with using react-responsive-modal and then switching to react-modal, but I'm encountering the same issue. Additionally, all my forms are built using react-hook-form. The problem arises when I have one modal triggering ano ...

AngularJS Service failing to appear on screen

I am trying to access my Github information using Github's API. I can see the correct information when I log my http request, but for some reason it is not showing up on the page. There are no errors being thrown, but the requested data is not display ...

I love the idea of the music playing on as I navigate between pages or tabs. Such a cool feature with Next

I'm looking to implement a music player within my next.js application. How can I ensure that the currently playing track doesn't stop when switching between pages? Essentially, I want the music playback to continue seamlessly as users navigate th ...

Set up a personalized React component library with Material-UI integration by installing it as a private NPM package

I have been attempting to install the "Material-UI" library into my own private component library, which is an NPM package built with TypeScript. I have customized some of the MUI components and imported them into another application from my package. Howe ...

Using RadSideDrawer with Typescript in Vue class components: A Step-by-Step Guide

I am attempting to integrate external components into Vue Typescript Class Components. Following the installation of the standard template, I made modifications to its <script> block based on this guide: import { Vue, Component, Prop } from "vue-pro ...

Make sure to save the HTML content after we make an AJAX call to retrieve it

Is there a way to call an HTML file using Ajax and then save the response as an HTML file in a specific location? I have been trying to make an Ajax call using jQuery, like shown below: $.ajax({ type: "POST", url: "../../../project/html/T ...

Is it possible to use abbreviations instead of full names for object properties in a JSON string?

I'm looking for a way to efficiently convert large and repetitive javascript objects into JSON strings. With the abundance of repeating property names in these objects, I want to streamline the process by replacing those names with predefined abbrevia ...

Combining two sets of JSON data in JavaScript with JQUERY

I am looking to combine two JSON datasets using JavaScript or jQuery. var object1 = [{ "id": 11, "name": "Vasanth", "username": "Vasanth.Rajendran", "email": "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="2c5a ...

The JSON array provides the ideal syntax for looping purposes

I am working with JSON data and trying to check if a hovered element matches the names 'sports' or 'technology'. If there is a match, I want to retrieve the corresponding 'text' and 'image' values. However, I am only ...

How to achieve multiplication in Javascript without utilizing the * operand

Challenge 1 Criteria: This problem involves working with two positive integers N and M. Outcome: Upon completion, the function should output the result of multiplying N and M. For instance, if you input 5 and 8 into the function, it should calculate and ...