0

I have various HTML elements defined in an XML file. I cant be able to display my XML element as whole but it has multiple rows and each row consists of checkboxes, File upload option, etc.

I am using Javascript to get these elements and then using XMLHTTPRequest, sending these requests to the controller to process.

Imagine HTML elements be like below:

Row1 ----  Checkbox1_Row1   TextDescription_Row1     FileUpload_Row1    
Row2 ----  Checkbox1_Row2   TextDescription_Row2     FileUpload_Row2    

I can have how many ever rows as possible.

Using Javascript, I am getting all these form elements and these elements are differentiated by Row number (Row1, Row2).

I am looping through each form elements and then

for(var j=0; j< formelements.length; j+++)
{
  if (formElements[j].type == "textbox")
   {
        Do something
    }
    elseif (formElements[j].type == "file")
    {
        var Base64String;
        var ready = false;
        var fileName = formElements[j].files[0].name;

        var check = function () {
        if (ready === true) {               
         array.push(Base64String);                           
         return;
         }
         setTimeout(check, 1000);
         }

         check();

         var reader = new FileReader();
          reader.onloadend = function (evt) {
          Base64String = evt.target.result;
          ready = true;
          };
         reader.readAsDataURL(file);
        }
    }

I am using an array to push all the values corresponding to each row and the array with final value will be sent to the controller after some alterations. Here for file upload option, I am reading the file from each row and converting them into binary format and sending to the controller. This approach works fine, if there is only one row. What happens with this approach when there are multiple rows is, while looping through the form element, it check everything for the first row (say textbox) and puts into the array but when it is file type, it goes to the loop and reads the file. Reading the file takes sometime here and by the time loop goes to the next form element (which is nothing but Row2). Now Row2 form element comes into picture and say, we do not upload any file, it will be null. Now check() function gets completed and file from row1 is read completely. Since the loop is already in for Row 2 form element, this file value is getting assigned to Row2 apart from null values. So Row2 will have both null value and file value when it comes to file type but there is no value for Row1. Similarly if I have many files in multiple rows, the file value gets assigned to which ever row form element that is there in current loop based on the time read by FileReader.

I need to make sure that file value is read completely before moving on to the next form element. How to achieve this?

************************Updates**********************

The question which was referred here marking mine as duplicate has only file type coming in and hence, they can loop through the file type. For me, form elements consists of Checkbox1_Row1, TextDescription_Row1, FileUpload_Row1, Checkbox1_Row2 , TextDescription_Row2, FileUpload_Row2.

I have to make sure that FileUpload_Row1 has right value read from the file before moving on to to next form element, here Checkbox1_Row2.

  • `.push()` `Base64String` to `array` within `onloadend` callback. – guest271314 May 15 '17 at 03:47
  • I have tried that, but still facing the same issue. – Sriram Chandramouli May 15 '17 at 14:44
  • Can you create a stacksnippets or plnkr http://plnkr.co to demonstrate issue? – guest271314 May 15 '17 at 14:46
  • http://plnkr.co/edit/mJMrUL1vbt3YGQg3GBLn?p=preview – Sriram Chandramouli May 16 '17 at 05:19
  • I just provided plnkr link. It doesnt work, but I have provided the things I expect over there. There are 3 file inputs here, and I have to make sure that I need to read all these 3 input file completely and push these 3 values present in check to the array fileList in the same order. Example: file 1 has some jpg file, file 2 is null and file 3 is pdf, then the array should hold value of jpg, null and pdf. Sorry about non working plnkr. – Sriram Chandramouli May 16 '17 at 05:25
  • `evt` should be `event`. `.push()` `event.target.result` to `fileList` array, do stuff when `fileList` `.length` is equal to `count` http://plnkr.co/edit/VCGPPbWcock0PgC9wMWi?p=preview – guest271314 May 16 '17 at 05:27

1 Answers1

1

evt should be event at evt.target.result. .push() event.target.result to fileList array, do stuff when fileList .length is equal to count

<!DOCTYPE html>
<html>

<head>
  <script>
    function myFunction() {
      var files = Array.prototype.map.call(
        document.querySelectorAll("[id^=myFile]")
        , function(input) {
            return {id:input.dataset.id, file: input.files[0]};
      });

      var count = files.length; // total number of files
      var fileList = []; // accepted files

      for (var i = 0; i < count; i++) {
        var file = files[i].file;
        var id = files[i].id;
        var filename = files[i].file.name;
        if (i >= count) {
          break;
        }

        var reader = new FileReader();

        reader.onload = (function(id, filename) {
          return function(event) {
            fileList.push({id, filename, file:event.target.result}); {
              if (fileList.length === count) {
                // do stuff with `fileList`
                console.log(fileList);
              }
            }
          }
        })(id, filename);
        reader.readAsDataURL(file);
      }
    }
  </script>
</head>

<body>
  <h1>Hello Plunker!</h1>
  <input type="file" id="myFile_row1" data-id="A">
  <input type="file" id="myFile_row2" data-id="B">
  <input type="file" id="myFile_row3" data-id="C">

  <button onclick="myFunction()">Try it</button>

</body>

</html>

plnkr http://plnkr.co/edit/VCGPPbWcock0PgC9wMWi?p=preview

guest271314
  • 1
  • 15
  • 104
  • 177
  • Thanks. One thing with snippet is, when you try to upload a larger file (say 5 MB) in first option (hello.pdf), a smaller files (may be in KB) in second (check.txt) and third upload option (image.jpg), first file takes more time to read since its size is large, but second and third file takes less time. Hence second file is printed first, third file is printed second and first file is printed last. This is the issue which I am facing for long time. The order must be preserved. How much ever time, it takes to read the first file, it should be read first completely, then second and then third. – Sriram Chandramouli May 16 '17 at 12:55
  • I tried an example and it behaved in that manner. It is moving to the next loop before even completing the current loop (when it is large file). Do you have any suggestion on how the order should be preserved? – Sriram Chandramouli May 16 '17 at 12:56
  • `FileReader` `load` event returns results asynchronously. What is the expected order? Order of selection of file by user? _"This is the issue which I am facing for long time. The order must be preserved."_ Is that requirement described at original Question? – guest271314 May 16 '17 at 14:22
  • I just made sure that I have changed my logic as per your suggestion, With respect to my question, there are multiple rows and each row consists of check box, text description and File upload option, I have to makes sure that I link the file to correct row later. With this approach, say there are 3 files, A,B and C. A file has large size and B/C files are of smaller size. FileReader takes sometime to read A file, by the time it is still reading, it moves to B and C file and completes reading, since they are of smaller size. Now it completes reading first file. – Sriram Chandramouli May 16 '17 at 14:28
  • So the order is B -> C -> A, So B file gets linked to Row 1, C file gets linked to row2 and A file gets linked to Row 3. Sometimes, if they take same time to read completely, C file is getting linked to Row 2 and A file is also getting linked to Row 2. – Sriram Chandramouli May 16 '17 at 14:30
  • That is not included at original Question as a requirement. You should be able to set a `data-*` attribute at `` at `html`, create an object which sets property to that `data-*` value, and value of object to `File` instance. At `load` event of `FileReader` set value of corresponding object property to `data URI` representation of file. E.g., `{"A":"data:image/png,..", "B":..}` – guest271314 May 16 '17 at 14:33
  • Sorry about that. Thanks a lot for your suggestion. This has been really of great help till now.. I will try and let you know about it. – Sriram Chandramouli May 16 '17 at 14:38
  • I am in the final step of my project. Now I am trying to send all the information through XMLHTTP request. I am onto similar kind of issue that I encountered while reading the file. I have posted a question with my issue. https://stackoverflow.com/questions/44103291/how-to-link-xmlhttp-request-to-right-response-in-case-of-multiple-ajax-request-i/44190055#44190055 – Sriram Chandramouli May 25 '17 at 21:57
  • It would be great if you could share any thoughts about this. This is my final step and I tried various approaches but I am not sure what I am missing. Thanks in advance and sorry for posting about another question in this post – Sriram Chandramouli May 25 '17 at 21:58