3

I'm using a multiple file input and then a for loop to iterate through the files using FileReader. JSfiddle here: https://jsfiddle.net/zLq8rsos/. It shows filename en contents correctly, but I don't understand why the counting doesn't work. If I choose one file, it's numbered '1' (why not 0?). If I choose two files, they're both counted '2'. What am I doing wrong?

function showDetails(file, content, n) {
  var start = content.substring(0, 9);
  var message = "File " + n + " is " + file.name + " and starts with " + start + " .<br>";
  $('#results').append(message);
}

$(document).ready(function() {
  $('#files').on('change', function(evt) {
    var files = evt.target.files;
    if (files) {
    	$('#results').text("");
      for (var i = 0, f; f = files[i]; i++) {
        var reader = new FileReader();
        reader.onload = (function(theFile) {
          return function(e) {
            var content = e.target.result;
            showDetails(theFile, content, i);
          };
        })(f);
        reader.readAsText(f, "UTF-8");
      }
    } else {
      console.log("Failed to load file(s)");
    };
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="file" id="files" name="files[]" multiple>
<div id="results">
</div>

4 Answers 4

2

Use closures Modify IIFE

function showDetails(file, content, n) {
  var start = content.substring(0, 9);
  var message = "File " + n + " is " + file.name + " and starts with " + start + " .<br>";
  $('#results').append(message);
}

$(document).ready(function() {
  $('#files').on('change', function(evt) {
    var files = evt.target.files;
    if (files) {
        $('#results').text("");
      for (var i = 0, f; f = files[i]; i++) {
        var reader = new FileReader();
        reader.onload = (function(theFile,count) {
          return function(e) {
            var content = e.target.result;
            showDetails(theFile, content, count);
          };
        })(f,i+1);
        reader.readAsText(f, "UTF-8");
      }
    } else {
      console.log("Failed to load file(s)");
    };
  });
});
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you and @nikhil. Apparently iteration and executing the code in the loop are two different things. This solution seems more KISS then nikhil adding an extra function wrapper, so I'm voting this up. Closures are new for me, interesting stuff. Adding this link: w3schools.com/js/js_function_closures.asp.
2

Problem Statement - In for loop when you are trying to access the value of i, it has already completed the iterations and hence the value because 1 for 1 file and 2 for 2 files.

You can update your for loop to

for (var i = 0, f; f = files[i]; i++) {
        (function(i){  // Added 
            var reader = new FileReader();
            reader.onload = (function(theFile) {
                return function(e) {
                    var content = e.target.result;
                    showDetails(theFile, content, i);
                };
            })(f);
            reader.readAsText(f, "UTF-8");
         })(i+1);
}

For reference - https://jsfiddle.net/zLq8rsos/1/

Comments

0

JSFIDDLE

All you need is to update the count through loop each time

function showDetails(file, content, n) {
  var start = content.substring(0, 9);
  var message = "File " + n + " is " + file.name + " and starts with " + start + " .<br>";
  $('#results').append(message);
}

$(document).ready(function() {
  $('#files').on('change', function(evt) {
    var files = evt.target.files;
    if (files) {
    	$('#results').text("");
      for (var i = 0, f; f = files[i]; i++) {
        var reader = new FileReader();
        var x=1;
        reader.onload = (function(theFile) {
          return function(e) {
            var content = e.target.result;
            showDetails(theFile, content, x);
            x++;
          };
        })(f);
        reader.readAsText(f, "UTF-8");
      }
    } else {
      console.log("Failed to load file(s)");
    };
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="file" id="files" name="files[]" multiple>
<div id="results">
</div>

Comments

0

Use jquery each, the index of the file start with 0

function showDetails(file, content, n) {
  var start = content.substring(0, 9);
  var message = "File " + n + " is " + file.name + " and starts with " + start + " .<br>";
  $('#results').append(message);
}

$(document).ready(function() {
  $('#files').on('change', function(evt) {
    var files = evt.target.files;
    if (files) {
    	$('#results').text("");
      $.each(files, function(i, f){
        var reader = new FileReader();
        reader.onload = (function(theFile) {
          return function(e) {
            var content = e.target.result;
            showDetails(theFile, content, i);
          };
        })(f);
        reader.readAsText(f, "UTF-8");
      });
    } else {
      console.log("Failed to load file(s)");
    };
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="file" id="files" name="files[]" multiple>
<div id="results">
</div>

Comments

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.