Set FileList of FileInput in Firefox

Both examples work in Chrome and Opera, but fail in Firefox 56.0.

I want to set the files FileList of a form's file input.[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;
};

On Chrome and Opera, selecting files in the first input, will also change the second. In Firefox, the second input doesn't change, even though the filelist appears to be correct in the console's output.

The overall goal is to create a drag-drop upload interface.
Prototype here.


The ability to set a FileList as the input.files property programmatically has been added as an PR to the specs three months ago, even if webkit allow this for years. Firefox has landed a patch in its next stable version, 57 and Edge is probably still working on it (I don't have an account to see the progress).It seems it has now landed in Edge too.

The main use case for this feature is to allow DataTransfer.files from eg a drag&drop event or a paste one to be added to an <input> field. As such, only a FileList is allowed (and null to clear the input).

So in the case exposed in the body of your question, I don't really see the point of using this feature between two <input> fields.

If you want to keep in memory selected FileList, you can always convert it as an Array of files.

If you want to be able to move your filled input in a <form> later on, you can do it directly with the inputElement and DOM methods.

And if you need to workaround the limitations this new feature leverages, you can always fill an FormData with the DataTransfer's files and send this FormData through xhr instead of using the default HTML form method.


And Since I first missed the real use-case, in the codepen, here is an possible implementation to workaround the drag&drop issue you are facing, even on older browsers that didn't support this new feature.

This uses an hidden input in the dropZone, which will catch the dropped files directly.

// 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>
链接地址: http://www.djcxy.com/p/64284.html

上一篇: ASP.NET MVC 2 InputExtensions在服务器上与本地计算机不同

下一篇: 在Firefox中设置FileInput的FileList