FileReader - 准备新文件,即使是同一个文件

FileReader - Preparing for new file, even the same one

我有几个加载文件 html 元素,例如:

<input type="file" id="loadFiles0" class="filesclass" name="file" />
<input type="file" id="loadFiles1" class="filesclass" name="file" />

我已经向它们添加了一个事件侦听器以捕获更改:

// Elsewhere
function myFunction(event){
    // Stuff
}

var el;
el = document.getElementById("loadFiles0");
el.addEventListener('change', myFunction, false);

正如许多人所知,要使负载第二次工作,即使是相同的文件名,您也必须将 html 元素的 'value' 设置为“”。这就是问题。我需要知道调用的是哪个加载文件元素。是 'loadFiles0' 还是 'loadFiles1' 等等

myFunction 看起来像这样 - 只是重要的部分:

function myFunction(evt){

    ...


    // We need to remove it so this is not handled again when we set value = ""
    this.removeEventListener('change', myFunction, false);

    ...

    var reader = new FileReader();
    reader.onload = function (e) {
        ...

        // HERE IS THE PROBLEM
        // I need a reference to the dom element that this is working on - call it 'ptr'
        // I cannot use 'this' in this function, because that refers to 'reader'
        // I need it so I can set its value to "", so even if the person reloads the same file, it will trigger a change
        // But I cannot be certain if it was 'loadFiles0' or 'loadFiles1' etc
        ptr.value = "";
        ptr.addEventListener('change', myFunction, false);
    };
}

所以问题是,如何在reader的onload函数中获取ptr?

I need to know which one of the load file elements did the call. Was it 'loadFiles0' or 'loadFiles1' etc.

myFunction 的事件回调中它将是 this,然后您可以在变量中记住它(可能是 ptr),或者如果您想使用 ES2015 (必要时进行转译)您可以使用箭头函数。

ptr:

function myFunction(evt){

    // ...


    this.removeEventListener('change', myFunction, false);

    var ptr = this; // *******

    // ...

    var reader = new FileReader();
    reader.onload = function (e) {
        ptr.value = "";
        ptr.addEventListener('change', myFunction, false);
    };
}

或者使用 ES2015+ 箭头函数:

function myFunction(evt){

    // ...


    this.removeEventListener('change', myFunction, false);

    // ...

    var reader = new FileReader();
    reader.onload = e => {                                   // ***
        this.value = "";                                     // ***
        this.addEventListener('change', myFunction, false);  // ***
    };
}

使用 setTimeout 模拟 reader.onload 回调的示例:

function myFunction(e) {
  var ptr = this;
  // This emulates the reader.onload callback:
  setTimeout(function() {
    console.log("reader.onload for " + ptr.id);
  }, 10);
}
Array.prototype.forEach.call(
  document.querySelectorAll("input[type=file]"),
  function(input) {
    input.addEventListener("change", myFunction, false);
  }
);
<input type="file" id="loadFiles0">
<input type="file" id="loadFiles1">
<input type="file" id="loadFiles2">

带有箭头函数的示例:

// ES2015 or higher (you can transpile if necessary)
function myFunction(e) {
  // This emulates the reader.onload callback:
  setTimeout(() => {
    console.log("reader.onload for " + this.id);
  }, 10);
}
Array.prototype.forEach.call(
  document.querySelectorAll("input[type=file]"),
  function(input) {
    input.addEventListener("change", myFunction, false);
  }
);
<input type="file" id="loadFiles0">
<input type="file" id="loadFiles1">
<input type="file" id="loadFiles2">