【问题标题】:HTML input file selection event not firing upon selecting the same file选择同一文件时未触发 HTML 输入文件选择事件
【发布时间】:2012-08-15 08:55:06
【问题描述】:

是否有机会检测到用户为file 类型的 HTML input 元素所做的每个文件选择?

这个问题之前被问过很多次,但是如果用户再次选择相同的文件,通常建议的onchange 事件不会触发。

【问题讨论】:

  • 如果用户点击取消,您的代码是否也必须触发?人们预计点击取消将无济于事,我认为大多数用户会进一步预计重新选择相同的文件将具有与取消相同的效果。我不知道这是否可能,但我建议你重新考虑这个设计。
  • 取消时不应触发或使其可检测到。它更多地意味着删除 UI ceveat:如果在选择文件后调用了某些操作,用户通常希望再次选择文件后该操作会重复。
  • 如果我们在对文件执行某些操作后将inputs 的值设置为'',也许我们可以有这种行为。但这也会删除可见的文件名。但是,这可能没问题,因为文件实际上已被处理,并且该操作的结果可能会出现在其他地方。
  • 请解释一下你想做什么?
  • 我想要的只是模拟桌面应用程序的老派行为。如果我在桌面应用程序中再次“打开”同一个文件,通常会重新加载它,或者如果对文件执行了某些操作(例如将其转换为另一种格式),则会再次执行此操作。这也是桌面用户对 Web 应用程序的期望,但 file 输入 onchange 事件并不相似。

标签: javascript html forms dom-events


【解决方案1】:

在每个onclick 事件上将input 的值设置为null。这将重置input 的值并触发onchange 事件,即使选择了相同的路径。

var input = document.getElementsByTagName('input')[0];

input.onclick = function () {
  this.value = null;
};
  
input.onchange = function () {
  console.log(this.value);
};
<input type="file" value="C:\fakepath">

注意:如果您的文件带有'C:\fakepath'前缀,这是正常的。这是一项安全功能,可防止 JavaScript 知道文件的绝对路径。浏览器内部仍然知道它。

【讨论】:

  • 我尝试了演示,但是(使用 Chrome 21)我不断得到 `C:\fakepath` + 然后是我选择的文件名(不包括路径)。但是,每次选择同一文件时都会显示警报。
  • @JasperdeVries 这是一项安全功能,可防止 JavaScript 知道文件的绝对路径。浏览器内部仍然知道路径。
  • 顺便说一句,null 是 唯一允许的值。因此,如果您尝试将其设置为 undefined 并获得异常,那么这就是原因。
  • 它在 IE11 中不能很好地工作,除非你做一个小改动:demo.
  • 最好将this.value = null 放在onchange 的末尾,因为无需单击(通过使用键盘)即可激活输入元素。 input.files 以后需要引用可以存储。
【解决方案2】:

每次用户点击字段时,使用 onClick 事件清除目标输入的值。这确保了同样的文件也会触发 onChange 事件。为我工作:)

onInputClick = (event) => {
    event.target.value = ''
}

<input type="file" onChange={onFileChanged} onClick={onInputClick} />

使用 TypeScript

onInputClick = ( event: React.MouseEvent<HTMLInputElement, MouseEvent>) => {
    const element = event.target as HTMLInputElement
    element.value = ''
}

【讨论】:

    【解决方案3】:
    <form enctype='multipart/form-data'>
        <input onchange="alert(this.value); this.value=null; return false;" type='file'>
        <br>
        <input type='submit' value='Upload'>
    </form>
    

    this.value=null; 仅适用于 Chrome,Firefox 可以正常使用 return false;

    这是FIDDLE

    【讨论】:

    • 简单而有效,刚刚在最新的 IE 和 chrome 中进行了测试,就像一个魅力。感谢分享
    【解决方案4】:

    在本文中,标题为“使用表单输入进行选择”

    http://www.html5rocks.com/en/tutorials/file/dndfiles/

    <input type="file" id="files" name="files[]" multiple />
    
    <script>
    function handleFileSelect(evt) {
    
        var files = evt.target.files; // FileList object
    
        // files is a FileList of File objects. List some properties.
        var output = [];
        for (var i = 0, f; f = files[i]; i++) {
         // Code to execute for every file selected
        }
        // Code to execute after that
    
    }
    
    document.getElementById('files').addEventListener('change', 
                                                      handleFileSelect, 
                                                      false);
    </script>
    

    它为“更改”添加了一个事件侦听器,但我对其进行了测试,即使您选择相同的文件而不是取消,它也会触发。

    【讨论】:

    • 考虑到在这种情况下“更改”的潜在含糊含义,您是否在多个浏览器中尝试过?您可能想指定您在网络上尝试过的那些,浏览器在这些事情上并不总是完全一致。
    • 您使用什么环境进行测试?我对 Chrome 的体验是我在问题中所说的,change 事件只会在文件名更改时触发。
    【解决方案5】:
    handleChange({target}) {
        const files = target.files
        target.value = ''
    }
    

    【讨论】:

    • 嘿 ngCourse !纯代码答案可能会解决问题,但如果您解释它们如何解决问题,它们会更有用。社区需要理论和代码才能完全理解您的答案。
    • 虽然此代码可能会解决问题,including an explanation 关于如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人。请edit您的答案以添加解释并说明适用的限制和假设。 From Review
    • 是的,这行得通。但正如@double-beep 所说,您应该解释答案。顺便说一句,谢谢
    【解决方案6】:

    清除第 0 个输入索引的值对我有用。请尝试下面的代码,希望它可以工作(AngularJs)。

              scope.onClick = function() {
                input[0].value = "";
                    input.click();
                };
    

    【讨论】:

      【解决方案7】:
      <input #myInput type="file" id="imgFile" (click)="$event.target.value=null"
             (change)="detectUploadedImage($event)" accept="image/*" />
      

      【讨论】:

        【解决方案8】:

        在文件加载成功后做任何你想做的事。在文件处理完成后将文件控制的值设置为空白字符串。所以即使文件名更改或不更改,也会始终调用 .change() .例如,您可以做这件事并像魅力一样为我工作

           $('#myFile').change(function () {
               LoadFile("myFile");//function to do processing of file.
               $('#myFile').val('');// set the value to empty of myfile control.
            });
        

        【讨论】:

          【解决方案9】:

          如果您使用 Angular,则使用两种方式绑定对我有用。

          这是我的 HMTL

          <input type="file" #upload name="upload" [(ngModel)]="inputValue"(change)='fileEvent($event)'/>
          

          和 TS..

            @ViewChild('upload') uploadBtn: HTMLElement;
          
            fileEvent(e: any){
              
             //file upload part... 
          
              this.inputValue = "";
            }
          

          【讨论】:

          • 我猜有很多框架(比如 Angular)可以让这个工作开箱即用。但这个问题是针对原版 JS 的。
          猜你喜欢
          • 1970-01-01
          • 2019-06-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-07-24
          相关资源
          最近更新 更多