使用FileReader遍历<input multiple>只能显示div网格中的最后一张图像

时间:2019-08-13 10:57:11

标签: javascript html image input filereader

我正在尝试创建一个HTML表单,该表单允许用户上传最多5张图片。用户选择图像后(使用<input multiple>从文件系统中选择图像),我想以5格显示(ID从#contactImage0到#contactImage4)。

为此,我使用香草JS遍历选定的图像,并将它们设置为相应div中的背景图像。问题在于,实际上只有选区中的最后一张图像出现。所有其他div保持为空。

经过一点调试后,我发现除了最后一个图像reader.result之外的所有图像都返回“”,但是我无法弄清为什么我传递给reader.readAsDataURL()的“ image”变量似乎是有效。

为什么会这样,我该如何解决?

HTML:
<div id="contactImage0" class="imagePreview"></div>
<div id="contactImage1" class="imagePreview"></div>
<div id="contactImage2" class="imagePreview"></div>
<div id="contactImage3" class="imagePreview"></div>
<div id="contactImage4" class="imagePreview"></div>
<input id="upload" type="file" onchange="LoadImage(this)" name="image" accept="image/*" multiple>

JavaScript:
function LoadImage(input){

            if (input.files.length > 5){
                alert("You may only select a maximum of 5 images!");
                // TODO: Remove selected images
                return;
            }
            var i;
            for (i = 0; i < input.files.length; i++){
                var image = input.files[i]
                var imageDiv = 'contactImage' + i.toString();
                var element = document.getElementById(imageDiv);
                var reader = new FileReader();
                reader.onloadend = function(){
                    element.style.backgroundImage = "url(" + reader.result + ")"; // <-- RETURNS EMPTY STRING (EXCEPT FOR LAST IMAGE)        
                }
                if(image){
                    reader.readAsDataURL(image);
                    }else{
                    }
            }
        }

CSS (Shouldn't be the cause of the problem but you never know):
.imagePreview{
    margin: .5em;
    display: inline-block;
    width: calc(100% - 1em);
    height: 80px;
    background-color: #fff;
    background-image:url('');
    background-size:cover;
    background-position: center;
}

1 个答案:

答案 0 :(得分:3)

请参见https://dzone.com/articles/why-does-javascript-loop-only-use-last-value

解决方案1-创建一个新函数setElementBackground

for (i = 0; i < input.files.length; i++) {
  setElementBackground(input.files[i], i);
}

function setElementBackground(file, i) {
  var image = file;
  var imageDiv = "contactImage" + i.toString();
  var element = document.getElementById(imageDiv);
  var reader = new FileReader();
  reader.onloadend = function() {
    element.style.backgroundImage = "url(" + reader.result + ")";
  };
  if (image) {
    reader.readAsDataURL(image);
  }
}

解决方案2-在循环内部使用另一个闭包

for (i = 0; i < input.files.length; i++) {
  (function() {
    var count = i;
    var image = input.files[count];
    var imageDiv = "contactImage" + count.toString();
    var element = document.getElementById(imageDiv);
    var reader = new FileReader();
    reader.onloadend = function() {
      element.style.backgroundImage = "url(" + reader.result + ")";
    };
    if (image) {
      reader.readAsDataURL(image);
    }
  })();
}