1

I need to retrieve dimensions and thumbnails of a set of images stored in the local file system. I have no problems with thumbnails but retrieving dimensions is somehow problematic. It works only in a third or half of all attempts. How to make it to work more reliably?

function handleFileSelect(evt) {
    let files = evt.target.files; // FileList object

    // Loop through the FileList and render image files as thumbnails.
    for (const file of files) {

      // Only process image files.
      if (!file.type.match('image.*')) {
        continue;
      }
      
      
      let reader = new FileReader();

      // Closure to capture the file information.
      reader.onload = (function(theFile) {
        return function(e) {
        
        let image = new Image();
        image.src = this.result;              
                
          // Render thumbnail.
          let item = document.createElement('li');

          item.innerHTML = `<img class="thumb" src="${e.target.result}" title="${escape(theFile.name)}"/>
                            <p>name: ${theFile.name}</p>
                            <p>width: ${image.width} px</p>
                            <p>height: ${image.height} px</p>`;
          document.getElementById('list').insertBefore(item, null);
        };
      })(file);

      // Read in the image file as a data URL.
      reader.readAsDataURL(file);
    }
  }

  document.getElementById('files').addEventListener('change', handleFileSelect, false);
  .thumb {
    height: 75px;
    border: 1px solid #000;
    margin: 10px 5px 0 0;
  }
  ul {
    list-style-type: none;
  }
  p {
    font-family: sans;
    font-size: 10px;
    margin: 0;
  }
<input type="file" id="files" name="files" multiple>
<ul id="list"></ul>
Honza Hejzl
  • 874
  • 8
  • 23
  • 1
    Possible duplicate of [JS - get image width and height from the base64 code](https://stackoverflow.com/questions/17774928/js-get-image-width-and-height-from-the-base64-code) – ADreNaLiNe-DJ Mar 28 '18 at 10:36

1 Answers1

0

It seems the crucial point is passing the FileReader (reader.onload) result (e.target.result) into the image.onload function. With that it works as expected. I hope I could say it was about proper callback usage.

function handleFileSelect(evt) {
let files = evt.target.files; // FileList object

// Loop through the FileList and render image files as thumbnails.
for (const file of files) {

  // Only process image files.
  if (!file.type.match('image.*')) {
    continue;
  }
  
  // Create new Filereader object
  let reader = new FileReader();

  // Closure to capture the file information
  reader.onload = (function(theFile) {
    
    return function(e) {
    
    let item = document.createElement('li');
    
    // Create new Image object
    let image = new Image();
    // Assign the Image object’s onload logic, everything happens here
    image.onload = function() {
    
     // Create elements, use Image object’s properties
     item.innerHTML = `<img class="thumb" src="${e.target.result}" title="${escape(theFile.name)}"/>
                        <p>name: ${theFile.name}</p>
                         <p>width: ${image.width} px</p>
                         <p>height: ${image.height} px</p>`;
      document.getElementById('list').insertBefore(item, null);      
    }
    // Load the image
    image.src = this.result;                    
      
    };
  })(file);

  // Read in the image file as a data URL
  reader.readAsDataURL(file);
}
  }

  document.getElementById('files').addEventListener('change', handleFileSelect, false);
  .thumb {
    height: 75px;
    border: 1px solid #000;
    margin: 10px 5px 0 0;
  }
  ul {
    list-style-type: none;
  }
  p {
    font-family: sans;
    font-size: 10px;
    margin: 0;
  }
<input type="file" id="files" name="files" multiple>
<ul id="list"></ul>
Honza Hejzl
  • 874
  • 8
  • 23