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.

6
  • .push() Base64String to array within onloadend callback. Commented May 15, 2017 at 3:47
  • I have tried that, but still facing the same issue. Commented May 15, 2017 at 14:44
  • Can you create a stacksnippets or plnkr plnkr.co to demonstrate issue? Commented May 15, 2017 at 14:46
  • plnkr.co/edit/mJMrUL1vbt3YGQg3GBLn?p=preview Commented May 16, 2017 at 5: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. Commented May 16, 2017 at 5:25

1 Answer 1

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

Sign up to request clarification or add additional context in comments.

9 Comments

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.
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?
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?
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.
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.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.