user7915134
user7915134

Reputation:

Uploading mulitple files(images) with "preview" crashes browser

For some odd reason when I try to upload multiple or even one image, my whole browser freezes and crashes after all the pictures get loaded in the .img_container. I don't know if my jquery code is faulty but this doesn't make any sense because my code worked perfectly fine before and I never touched it. Now out of no where it's crashing my browser. I am using Firefox and I tried to use Chrome but I guess my jquery code or css is not working with Chrome cause the pictures don't load in my preview div. This is the second time making this post because I thought of uploading the pictures in the snippet below and still crashed my browser yet again.

$(function() {
        var imagesPreview = function(input, placeToInsertImagePreview) {

            if (input.files) {
                var filesAmount = input.files.length;

                for (i = 0; i < filesAmount; i++) {
                    var reader = new FileReader();

                    reader.onload = function(event) {
                        $($.parseHTML('<img>')).attr('src', event.target.result).appendTo(placeToInsertImagePreview);
                        $(document).find('img img').addClass('imageClass');
                    }

                    reader.readAsDataURL(input.files[i]);
                }
            }

        };

        $('#upload-image').on('change', function() {
            imagesPreview(this, 'img.image');
        });
    });
input {
  width: 100%;
  font-size: 16px;
  border: 2px solid #FFF;
  border-radius: 3px;
  padding: 5px 5px;
  margin: 3px 3px;
  box-sizing: border-box;
}
.field-wrap {
  position: relative;
  margin-bottom: 10px;
  padding-top: 8px;
  width: 40%;
}
.form {
  background: #CCC;
  max-width: 100%;
  border-radius: 4px;
  margin: 20px;
}
.img_container {
    justify-content: center;
    display: flex;
    border: 2px solid #CCC;
    min-height: 220px;
    max-height: 220px;
    overflow: scroll;
    user-drag: none;
    user-select: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<form id='imageForm' action='' method='POST' enctype='multipart/form-data'>
    <div class="field-wrap">
        <input id='upload-image' type='file' name='files[]' multiple>
    </div>
    <div class="field-wrap">
        <input type='submit' value='Upload'>
    </div>
    <div class='img_container'><img class='image'></div>
</form>

Upvotes: 0

Views: 689

Answers (2)

Endless
Endless

Reputation: 37855

What was so strange to me was that you try to append images into a self enclosing tag such as <img class='image'> a image can't contain any other elements.

So here is what i did:

  • I removed the asynchronous FileReader with URL.createObjectURL(file) this is faster, smarter and don't require any decoding/encoding back and forth between base64
  • i then revoke the objectUrl after the image is loaded to release any references so it can be garbage collected by the browser
  • also you don't have to check for if(input.files) any more all modern browser have that now.
  • and i changed the file input to only accept image/* to make it easier to pick images from the dialog

jQuery(function($) {
  function imagesPreview(input, placeToInsertImagePreview) {
    var len = input.files.length;

    for (i = 0; i < len; i++) {
      var img = new Image();
      img.src = URL.createObjectURL(input.files[i])
      img.className = 'imageClass';
      img.onload = function(){
        URL.revokeObjectURL(img.src)
      }
      $(img).appendTo(placeToInsertImagePreview);
    }
  };

  $('#upload-image').on('change', function() {
    imagesPreview(this, 'div.image');
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<form id='imageForm' action='' method='POST' enctype='multipart/form-data'>
  <div class="field-wrap">
    <input id='upload-image' accept="image/*" type='file' name='files[]' multiple>
  </div>
  <div class="field-wrap">
    <input type='submit' value='Upload'>
  </div>
  <div class='img_container'><div class='image'></div>
</form>

Upvotes: 0

ferhado
ferhado

Reputation: 2604

Here is an example which may help you:

function toBase64(file) {
  return new Promise(function(resolve, reject) {
    var reader = new FileReader();
    reader.onload = function() {
      resolve(reader.result);
    };
    reader.onerror = reject;
    reader.readAsDataURL(file);
  });
}

function preview(files) {
  $('.img_container').html('')
  for (var i in files) {
    var promise = toBase64(files[i]);
    promise.then(function(result) {
      $('.img_container').append(`<img class="image" src="${result}">`)
    });
  }
}
   
.img_container {
  border: 2px solid #CCC;
  min-height: 158px;
}
.image{width:100px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input onchange="preview(this.files)" type='file' name='files[]' multiple>
<div class='img_container'></div>

Upvotes: 0

Related Questions