Jam3sn
Jam3sn

Reputation: 1087

readAsDataURL is not a blob, yet the images show

I have a file input which then preview the images after adding. The images show, but I get: Uncaught TypeError: Failed to execute 'readAsDataURL' on 'FileReader': parameter 1 is not of type 'Blob'."

What's causing this, surely they wouldn't show still?

$('#image-upload-input').on('change', function() {
    var files = document.getElementById('image-upload-input').files;

    for (var key in files) {
        if (files[key]) {
            var reader = new FileReader();

            reader.onload = function(e) {
                $('.image-upload-container').append('<img src="'+ e.target.result +'" style="width: 100px;">');
            }

            reader.readAsDataURL(files[key]);
        }
    }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<input id="image-upload-input" type="file" multiple>

<div class="image-upload-container"></div>

Upvotes: 0

Views: 1539

Answers (3)

Endless
Endless

Reputation: 37975

I would have ditched the FileReader for URL.createObjectURL and just use a regular for loop

$('#image-upload-input').on('change', function() {
  var files = document.getElementById('image-upload-input').files;

  for (var i = 0; i < files.length; i++) {
    var url = URL.createObjectURL(files[i]);
    $('.image-upload-container').append('<img src='+ url +' style="width: 100px;">');
  }
});

and possible added this extra attribute to the input

accept="image/*"

Upvotes: 0

Oleg Imanilov
Oleg Imanilov

Reputation: 2751

Good example of few issues together.

  1. Exception you get - is because files isn't real array, so for ... in - iterates over "0", "1"... "item","length" keys.
  2. You can't use async function inside loop without isolating the scope
  3. My personal opinion: don't use jQuery if you can :-)

$('#image-upload-input').on('change', function() {
    var files = document.getElementById('image-upload-input').files;

    for (var key=0; key < files.length; key++) {
        (function(){
            var reader = new FileReader();
            var file = files[key];
            reader.onload = function(e) {
                var img = document.createElement('img');
                img.style= "width:100px";
                img.src = reader.result;
                $('.image-upload-container').append($(img));
            }
            reader. readAsDataURL(file);
        })();
    }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<input id="image-upload-input" type="file" multiple>

<div class="image-upload-container"></div>

Upvotes: 0

Randy Casburn
Randy Casburn

Reputation: 14185

You are misusing the for( in ) loop. As it iterates it chokes on the length property - which is not a Blob Object. This happens because the for( in ) iterates over all (enumerable) object properties and not just "own properties". Reference

You have two choices:

  • Stick to the traditional (and always works) for() loop
  • Use the for( of ) loop

The for( of ) loop will only iterate "own properties" while the traditional for() loop will always, always work when a length property is available.

$('#image-upload-input').on('change', function() {
    var files = document.getElementById('image-upload-input').files;

    for(file of files) {
        if (file) {
            var reader = new FileReader();

            reader.onload = function(e) {
                $('.image-upload-container').append('<img src="'+ e.target.result +'" style="width: 100px;">');
            }

            reader.readAsDataURL(file);
        }
    }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<input id="image-upload-input" type="file" multiple>

<div class="image-upload-container"></div>

Upvotes: 1

Related Questions