【问题标题】:Only allow one image at the same time with File API?File API 只允许同时使用一张图片?
【发布时间】:2018-04-22 19:12:00
【问题描述】:

文件 API 只允许同时使用一张图片? 什么是同时只为一张图片设置限制的正确方法是什么?

<input id="browse" type="file" multiple>
<div id="imgs"></div>

<style type="text/css">
  #imgs {
    height: imageheight;
    width: imagewidth;
    position: absolute;
    top: 39px;
    left: 9px;
  }
</style>

<script type="text/javascript">
  window.URL = window.URL || window.webkitURL;
  var elBrowse = document.getElementById("browse"),
    elPic = document.getElementById("imgs"),
    useBlob = false && window.URL;

  function readImage(file) {
    var reader = new FileReader();
    reader.addEventListener("load", function() {

      var image = new Image();
      image.addEventListener("load", function() {
        elPic.appendChild(this);
      });

      image.src = useBlob ? window.URL.createObjectURL(file) : reader.result;
    });

    reader.readAsDataURL(file);
  }
  elBrowse.addEventListener("change", function() {

    var files = this.files; {
      for (var i = 0; i < files.length; i++) {
        var file = files[i];
        if ((/\.(png|jpeg|jpg|gif)$/i).test(file.name)) {

          readImage(file);
        }
      }
    }
  });
</script>

【问题讨论】:

  • 为什么不直接从文件输入中删除多个属性呢?或者我没有正确理解你的意图。

标签: javascript fileapi


【解决方案1】:

一种解决方案可能是这样的承诺链:

function readImage(file) {
  //wrap readImage body into a promise
  return new Promise((resolve) => {
    var reader = new FileReader();
    reader.addEventListener("load", function () {

      var image = new Image();
      image.addEventListener("load", function () {
        elPic.appendChild(this);
        //resolve the promise after the child is appended so the caller would know when to start the next one
        resolve();
      });

      image.src = useBlob ? window.URL.createObjectURL(file) : reader.result;
    });

    reader.readAsDataURL(file);
  });
}

elBrowse.addEventListener("change", function () {

  var files = this.files; {
    //start the chain
    var chain = Promise.resolve();
    for (var i = 0; i < files.length; i++) {
      //use let to have properly scoped variable
      let file = files[i];
      if ((/\.(png|jpeg|jpg|gif)$/i).test(file.name)) {
        //append functions to call to the chain
        chain = chain.then(() => readImage(file));
      }
    }
  }
});

对下一个 readImage() 的调用是在上一个调用 resolve() 之后执行的 - 在加载和附加图像之后。

您可能还想考虑使用 loadend 事件,即使由于某种原因加载失败也会发出它,因此它不会破坏您的链条。 https://developer.mozilla.org/en-US/docs/Web/Events/loadend

【讨论】:

  • 我尝试了promise链的解决方案,但是由于某种原因加载例程会失败。
  • 不存在错误,但图像不会显示实现承诺链。我想知道为什么。实际上,必须有一种方法可以在不丢失主要功能的情况下实现对一个图像的新限制。否则,我可以使用带有 jQ​​uery 的简短解决方案进行上传,这是我这次更愿意避免的事情。
  • 它适用于我的 Chrome。唯一的问题是该文件必须用let 而不是var 声明,否则它会多次上传同一个文件。
  • 感谢您的帮助。是的 - 它现在可以在 Chrome 中正常运行。
【解决方案2】:

我开始了一种新的方法,可以达到预期的结果。

<body style="margin:8px">
<img style="position:absolute; top:39px; left:9px"
     height="imageheight" width="imagewidth">

<input type="file" onchange="previewFile()">
<script type="text/javascript">
 function previewFile() {
   var preview = document.querySelector('img');
   var file    = document.querySelector('input[type=file]').files[0];
   var reader  = new FileReader();
   reader.addEventListener("load", function () {
    preview.src = reader.result;
     }, false);
     if ((/\.(png|jpeg|jpg|gif)$/i).test(file.name)) {
   reader.readAsDataURL(file); }
 }
</script>

【讨论】:

    猜你喜欢
    • 2017-05-21
    • 2015-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多