【问题标题】:Set FileList of FileInput in Firefox在 Firefox 中设置 FileInput 的 FileList
【发布时间】:2017-10-16 22:12:09
【问题描述】:

这两个例子都在 ChromeOpera 中工作,但在 Firefox 56.0 中失败。

我想设置表单的文件输入files FileList。[Codepen]

HTML

<form>
  <input type="file" id="input1" multiple>
  <br>
  <input type="file" id="input2" multiple>
</form>

JAVASCRIPT

var input1 = document.getElementById("input1");
var input2 = document.getElementById("input2");

input1.onchange = function () {
  console.log(input1.files);
  input2.files = input1.files;
};

在 Chrome 和 Opera 上,在第一个输入中选择文件也会更改第二个。在 Firefox 中,第二个输入不会改变,即使 filelist 在控制台的输出中看起来是正确的。

总体目标是创建一个拖放上传界面。
Prototype here

【问题讨论】:

    标签: javascript file firefox


    【解决方案1】:

    以编程方式将 FileList 设置为 input.files 属性的功能已在三个月前添加为 an PR to the specs,即使 webkit 允许这样做多年。 Firefox has landed a patch 的下一个稳定版本 57 和 Edge is probably still working on it(我没有帐户可以查看进度)。现在它似乎也登陆了 Edge。

    此功能的主要用例是允许将来自例如拖放事件或粘贴事件的DataTransfer.files 添加到&lt;input&gt; 字段。因此,只允许使用 FileList(并且 null 清除输入)。

    因此,在您的问题正文中公开的情况下,我真的看不出在两个 &lt;input&gt; 字段之间使用此功能的意义。

    如果您想在内存中保留选定的 FileList,您可以随时将其转换为文件数组。

    如果您希望稍后能够在&lt;form&gt; 中移动填充的输入,您可以直接使用 inputElement 和 DOM 方法来实现。

    如果您需要解决此新功能所利用的限制,您始终可以使用 DataTransfer 的文件填充 FormData 并通过 xhr 发送此 FormData,而不是使用默认的 HTML 表单方法。


    而且由于我第一次错过了真正的用例,在 codepen 中,这里有一个可能的实现来解决您面临的拖放问题,即使在不支持此新功能的旧浏览器上也是如此。

    这在 dropZone 中使用了一个隐藏的输入,它将直接捕获被删除的文件。

    // called when the input hidden in the dropZone changes
    function handleDroppedChange(evt) {
      this.removeEventListener('drop', handleDroppedChange); // only once
      // create a new hidden input
      var clone = this.cloneNode();
      clone.addEventListener('change', handleDroppedChange);
      clone.addEventListener('change', handleBasicChange);
      this.parentNode.insertBefore(clone, this);
      // replace the visible one with the current hidden one
      var form = document.querySelector('form');
      var previous = form.querySelector('input[type=file]');
      form.insertBefore(this, previous);
      form.removeChild(previous);
      this.id = previous.id; // for the <label>
    }
    // add first listeners
    var hiddenTarget = dropzone.querySelector('input[type="file"]');
    hiddenTarget.addEventListener('change', handleDroppedChange);
    hiddenTarget.addEventListener('change', handleBasicChange);
    file_input.addEventListener('change', handleBasicChange);
    // handle drop over enter leave as usual on the parent
    dropzone.ondragover = dropzone.ondragenter = function(evt) {
      evt.preventDefault();
      dropzone.className = "drag";
    };
    
    dropzone.ondragleave = function(evt) {
      evt.preventDefault();
      dropzone.className = "";
    };
    
    dropzone.ondrop = function(evt) {
      dropzone.className = "";
      console.log("drop");
    };
    
    // will trigger for any kind of changes (dropped or manual)
    function handleBasicChange(evt) {
      var file_names = Array.prototype.map.call(this.files, function(f){return f.name;});
      label.innerHTML = "Changed " + file_names.join('<br>');
      // start upload process
    };
    #dropzone {
      display: inline-block;
      padding: 25px;
      border: 8px dashed #b11;
      position: relative;
    }
    
    #dropzone.drag {
      border-color: #f74;
    }
    #dropzone>input{
      opacity: 0;
      position: absolute;
      height: 100%;
      width: 100%;
      left: 0;
      top: 0;
    
    /* below rules avoid clicks on hidden input */
      pointer-events: none; 
      }
    #dropzone.drag>input{
      pointer-events: all;
      }
    <form>
      <input type="file" id="file_input" multiple>
    </form><br><br>
    
    <div id="dropzone">
      <label id="label" for="file_input">Drop here.</label>
      <!-- we use an hidden file input to catch the dropped files -->
      <input type="file" multiple>
    </div>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-02-16
      • 2019-07-06
      • 1970-01-01
      • 2018-08-26
      • 2017-10-27
      • 1970-01-01
      • 2013-02-20
      相关资源
      最近更新 更多