HTML5 File API 按顺序包含多个文件,而不是一次全部

Posted

技术标签:

【中文标题】HTML5 File API 按顺序包含多个文件,而不是一次全部【英文标题】:HTML5 File API with Multiple Files in sequence instead of all at once 【发布时间】:2019-01-13 19:15:15 【问题描述】:

我正在构建一个 BackboneJS/Marionette 应用程序,目前正在尝试允许用户上传多个文件。

这在他们同时选择多个文件时有效,但我希望具有允许他们选择 1 个文件然后再次单击输入并尽可能添加到原始 FileList 对象的功能。

或者我想找到一种方法,让我的保存功能在需要时从多个输入中获取文件。

我愿意接受任何和所有建议

这是我正在使用的 html5 文件 API 代码,我正在使用 MDN HTML5 File API guide 提供的 jquery/js

<input id="uploads" name="uploads" type="file" class="file uploads file1" multiple style="display: none"/>
<a href="#" id="fileSelect">Select File 1</a><br>

【问题讨论】:

【参考方案1】:

HTMLInputElement 中的 FileList 对象(它是保存 input.files 中文件的底层对象)只能被修改以完全清除它(使用input.value = null)。

There are now ways 实际绕过这个,由DataTransfer constructor 引入,但截至今天,只有 Chrome 和最新的 Firefox 支持这个构造函数。

因此,在这种情况下,最简单的方法是不依赖默认 UI,而是将所有文件移动到常规数组中,以便您可以随意编辑。

这是一种混乱的方式,但它可能会给你一个很好的起点: 它确实向您的输入添加了一个数组,该数组会将添加的文件保存在内存中。

// The multiUp function will be called each time our hidden input is changed
document.querySelector('input').addEventListener('change', multiUp, false);

function multiUp(e)
  // if it's the first time we call it
  if(!this.multiFiles)
    // create the array that will keep our files in memory
    this.multiFiles = [];
    // add a pointer to the span where we'll display the file names
    this.__fileHolder = document.querySelector('#fileHolder');
    
  // each time : empty the fileHolder span
  this.__fileHolder.innerHTML = '';
  var i;
  // add the new files to our array
  for(i = 0; i<this.files.length; i++)
    this.multiFiles.push(this.files[i]);
    

  for(i = 0; i<this.multiFiles.length; i++)
    // display every file name to our fileHolder
    this.__fileHolder.appendChild(document.createTextNode(this.multiFiles[i].name) );
    // add a button to remove the file from the list
    addDeleteBtn(i, this);
    
  

// Tell the add span to act as a trigger to our input
document.querySelector('#add').addEventListener('click', function() document.querySelector('input').click(), false);

function addDeleteBtn(f, input)
  // create the element
  var del= document.createElement('span');
  del.innerHTML = ' (x) ';
  del.className = 'deleteBtn';
  del.title = 'remove this file';
  // add an onclick event
  del.addEventListener('click', function()
    // update the array
    input.multiFiles.splice(f, 1);
    // update the fileHodler
    input.__fileHolder.innerHTML = '';
    var fileLength = input.multiFiles.length;
    if(fileLength>0)
      for(var i = 0; i<fileLength; i++)
        input.__fileHolder.appendChild(document.createTextNode(input.multiFiles[i].name) );
        addDeleteBtn(i, input);
        
      
    else input.__fileHolder.innerHTML = 'No files selected.';
    , false);
  input.__fileHolder.appendChild(del);
  
#add font-size: 2em; cursor: pointer;
#fileHolder color: rgba(0,0,0,.7); max-width: 80%; font-size: 70%; overflow-x: auto; white-space: nowrap; display: inline-block;
.deleteBtncursor: pointer; color: #000;
<div class="multiUp">
<span id="add">+</span>
<span id="fileHolder">No files selected.</span>
<input multiple type="file" style="display: none"/>
</div>

您现在可以通过遍历document.querySelector('.multiUp&gt;input').multiFiles 来访问这些文件。

【讨论】:

这个解决方案的唯一问题是,当我实际去保存和上传时,它是从输入 FileList 对象中提取的,该对象只会选择最后一个文件,而不是抓取我们创建的数组 @LoganRx 不,请仔细阅读最后一句,在 sn-p 之后:“您现在可以通过迭代 document.querySelector('.multiUp&gt;input').multiFiles. 来访问这些文件”实际上,您可以将 document.querySelector('.multiUp&gt;input') 更改为您想要的任何变量已为此输入设置。但是您必须将您使用 theInput.files 所做的更改为 theInput.multiFiles 是的,对不起,我看错了,我需要看看应用程序现在是如何抓取文件并将其从 FileList 对象引导回数组,太棒了,现在来追踪它

以上是关于HTML5 File API 按顺序包含多个文件,而不是一次全部的主要内容,如果未能解决你的问题,请参考以下文章

如何在 html 5 中按顺序播放多个音频文件?

使用 glob 读取多个 CSV 导致顺序错误 [重复]

使用 JavaScript 按顺序播放 MP3 文件,无需 HTML5 音频

HTML5 使用 AJAX 上传多个文件?

HTML5 File API:在 FileReader 回调中获取 File 对象

HTML5 File API 中的 FileReader.readAsText 如何工作?