Search code examples
javascriptfilereaderfileapi

Code runs inconsistently and needs multiple page reloads to display results


I'm using the FileReader function to load a local image file, get the height and width in pixels and convert those two into millimeters for printing in 300 dpi.

the code displays the thumbnail correct every time but the measurements are sometimes updated on the first try, sometimes only after selecting the file again, sometimes using F5 or even CRTL + F5 for reload.

I've tried to troubleshoot the reader.addEventListener function, the Math.round function, basically blindly trial and error.

<!doctype html>
<html lang="en">
 <head>
 <meta charset="utf-8">
 <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
 <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

 <title>Pixelkonverter</title>
</head>

<body>
 <div class="container">
   <div class="row">
     <div class="col-sm my-5">
      <input type="file" onchange="previewFile()"><br>
      <hr>
      <img src="" height="200" alt="Bildvorschau...">
    </div>
    <div class="col-sm my-5">
      Bei 300 dpi ist das gewählte Bild <br>
      <span id="height_mm"></span> mm hoch </br>
      <span id="width_mm"></span> mm breit </br>
    </div>
  </div>
</div>

<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>

<script>
  function previewFile() {
    var preview = document.querySelector('img');
    var file    = document.querySelector('input[type=file]').files[0];
    var reader  = new FileReader();
    var img = new Image();
    var height_mm = 0;
    var width_mm = 0;


    reader.addEventListener("load", function () {
      preview.src = reader.result;
      img.src = reader.result;
      var height_mm = Math.round((img.height * 25.4 / 300) * 100) / 100;
      var width_mm =  Math.round((img.width * 25.4 /300) * 100) / 100;
      document.getElementById("height_mm").innerHTML = height_mm;
      document.getElementById("width_mm").innerHTML = width_mm;
    }, false);


    if (file) {
      reader.readAsDataURL(file);
    }
  }
</script>
</body>
</html>

I'd like to be able to display the correct results of the calculation every single time a file is selected.


Solution

  • function previewFile() {
    var preview = document.querySelector('img');
    var file    = document.querySelector('input[type=file]').files[0];
    var reader  = new FileReader();
    var img = new Image();
    var height_mm = 0;
    var width_mm = 0;
    
    
    reader.addEventListener("load", function () {
      preview.src = reader.result;
      img.onload = function() {
           var height_mm = Math.round((img.height * 25.4 / 300) * 100) / 100;
           var width_mm =  Math.round((img.width * 25.4 /300) * 100) / 100;
           document.getElementById("height_mm").innerHTML = height_mm;
           document.getElementById("width_mm").innerHTML = width_mm;
      }
      img.src = reader.result;
    }, false);
    
    
    if (file) {
      reader.readAsDataURL(file);
    }
    }
    

    I have explained why this may work in the comments above