【问题标题】:How to detect input type=file "change" for the same file?如何检测同一文件的输入类型=文件“更改”?
【发布时间】:2011-05-05 18:55:15
【问题描述】:

我想在用户选择文件时触发一个事件。如果用户每次都更改文件,则使用 .change 事件这样做。

但如果用户再次选择相同的文件,我想触发该事件。

  1. 用户选择文件A.jpg(事件触发)
  2. 用户选择文件B.jpg(事件触发)
  3. 用户选择文件B.jpg(事件不触发,我希望它触发)

我该怎么做?

【问题讨论】:

    标签: jquery html events cross-browser


    【解决方案1】:

    根据被触发的事件类型,对于 React,您可能需要将解决方案调整为:

    onClick={(event): string => (event.currentTarget.value = "")}

    【讨论】:

      【解决方案2】:

      最简单的方法是直接在 change 或 input 事件中将输入值设置为空字符串,反正大多数情况下都会监听。

      onFileInputChanged(event) {
           // todo: read the filenames and do the work
           
           // reset the value directly using the srcElement property from the event
           event.srcElement.value = ""
      }
      

      【讨论】:

        【解决方案3】:

        这是我发现对我有用的 React-y 方式解决方案:

        onClick={event => event.target.value = null}

        【讨论】:

        • 谢谢!修改你对 @click="(e) => e.target.value = null" 的回答给了我一个 Vue 解决方案。
        【解决方案4】:

        为输入创建一个点击事件和一个更改事件。 click事件清空输入,change事件包含你要执行的代码。

        因此,当您单击输入按钮时(在选择文件窗口打开之前),单击事件将为空,因此当您选择文件时始终会触发更改事件。

        $("#input").click(function() {
          $("#input").val("")
        });
        
        $("#input").change(function() {
          //Your code you want to execute!
        });
        <input id="input" type="file">
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js">
        </script>

        【讨论】:

          【解决方案5】:

          你可以欺骗它。删除文件元素并将其添加到 change 事件的相同位置。它会擦除文件路径,使其每次都可以更改。

          Example on jsFiddle.

          或者您可以简单地使用.prop("value", ""),参见this example on jsFiddle

          • jQuery 1.6+ prop
          • 早期版本attr

          【讨论】:

          • @Pekka:不完全是。但他只能适应它。假设他需要发布文件。在发布之后,他可以调用一个 js 函数,该函数将删除和添加新的文件选择器。这是可行的。
          • 请注意,当您使用 .attr("value", "").val("")(如下面的 @wagner-leonardi 建议的那样)时,Internet Explorer 将触发更改事件,而 chrome 则不会
          • 因为 "value" 是一个属性而不是输入的属性,所以推荐的 jQuery 用法是.prop("value", "")
          【解决方案6】:

          您可以做的最简单的事情可能是将值设置为空字符串。即使再次选择相同的文件,这也会强制它每次“更改”文件。

          &lt;input type="file" value="" /&gt;

          【讨论】:

          • 这应该是公认的答案 - 它根本不需要 javascript。
          • @AlexanderMihailov 当用户实际选择文件时,它仍然如此。
          【解决方案7】:

          每次用户点击字段时,使用 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 = ''
          }
          

          【讨论】:

            【解决方案8】:

            VueJs 解决方案

            <input
                            type="file"
                            style="display: none;"
                            ref="fileInput"
                            accept="*"
                            @change="onFilePicked"
                            @click="$refs.fileInput.value=null"
            >
            

            【讨论】:

            • 感谢您提供这个变体答案
            【解决方案9】:

            灵感来自@braitsch,我在 AngularJS2 input-file-component987654321@ 中使用了以下内容

            <input id="file" onclick="onClick($event) onchange="onChange($event)" type="file" accept="*/*" />
            
            export class InputFile {
            
                @Input()
                file:File|Blob;
            
                @Output()
                fileChange = new EventEmitter();
            
                onClick(event) {
                    event.target.value=''
                }
                onChange(e){
                    let files  = e.target.files;
                    if(files.length){
                        this.file = files[0];
                    }
                    else { this.file = null}
                    this.fileChange.emit(this.file);
                }
            }
            

            onClick(event) 救了我 :-)

            【讨论】:

              【解决方案10】:

              相信我,它一定会对你有所帮助!

              // there I have called two `onchange event functions` due to some different scenario processing.
              
              <input type="file" class="selectImagesHandlerDialog" 
                  name="selectImagesHandlerDialog" 
                  onclick="this.value=null;" accept="image/x-png,image/gif,image/jpeg" multiple 
                  onchange="delegateMultipleFilesSelectionAndOpen(event); disposeMultipleFilesSelections(this);" />
              
              
              // delegating multiple files select and open
              var delegateMultipleFilesSelectionAndOpen = function (evt) {
              
                if (!evt.target.files) return;
              
                var selectedPhotos = evt.target.files;
                // some continuous source
              
              };
              
              
              // explicitly removing file input value memory cache
              var disposeMultipleFilesSelections = function () {
                this.val = null;
              };
              

              希望这对你们中的许多人有所帮助。

              【讨论】:

                【解决方案11】:

                因此,除非您存储每个文件并以编程方式比较它们,否则无法 100% 确保他们选择相同的文件。

                您与文件交互的方式(当用户“上传”文件时 JS 所做的)是HTML5 File APIJS FileReader

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

                https://scotch.io/tutorials/use-the-html5-file-api-to-work-with-files-locally-in-the-browser

                这些教程向您展示了如何在文件上传时捕获和读取元数据(存储为 js 对象)。

                创建一个触发“onChange”的函数,该函数将读取->存储->将当前文件的元数据与以前的文件进行比较。然后您可以在选择所需文件时触发您的事件。

                【讨论】:

                  【解决方案12】:

                  我遇到了同样的问题,我通过了上面的解决方案,但他们没有得到任何很好的解释到底发生了什么。

                  我写的这个解决方案https://jsfiddle.net/r2wjp6u8/ 没有对 DOM 树做很多改变,它只是改变了输入字段的值。从性能方面来说应该会好一点。

                  小提琴链接:https://jsfiddle.net/r2wjp6u8/

                  <button id="btnSelectFile">Upload</button>
                  
                  <!-- Not displaying the Inputfield because the design changes on each browser -->
                  <input type="file" id="fileInput" style="display: none;">
                  <p>
                    Current File: <span id="currentFile"></span>
                  </p>
                  <hr>
                  <div class="log"></div>
                  
                  
                  <script>
                  // Get Logging Element
                  var log = document.querySelector('.log');
                  
                  // Load the file input element.
                  var inputElement = document.getElementById('fileInput');
                  inputElement.addEventListener('change', currentFile);
                  
                  // Add Click behavior to button
                  document.getElementById('btnSelectFile').addEventListener('click', selectFile);
                  
                  function selectFile() {
                    if (inputElement.files[0]) {
                      // Check how manyf iles are selected and display filename
                      log.innerHTML += '<p>Total files: ' + inputElement.files.length + '</p>'
                      // Reset the Input Field
                      log.innerHTML += '<p>Removing file: ' + inputElement.files[0].name + '</p>'
                      inputElement.value = '';
                      // Check how manyf iles are selected and display filename
                      log.innerHTML += '<p>Total files: ' + inputElement.files.length + '</p>'
                      log.innerHTML += '<hr>'
                    }
                  
                    // Once we have a clean slide, open fiel select dialog.
                    inputElement.click();
                  };
                  
                  function currentFile() {
                      // If Input Element has a file
                    if (inputElement.files[0]) {
                      document.getElementById('currentFile').innerHTML = inputElement.files[0].name;
                    }
                  }
                  
                  </scrip>
                  

                  【讨论】:

                    【解决方案13】:

                    默认情况下,如果输入具有多个属性,则在选择文件后会清除输入元素的 value 属性。如果您不清除此属性,则如果您选择相同的文件,则不会触发“更改”事件。您可以使用multiple 属性管理此行为。

                    <!-- will be cleared -->
                    <input type="file" onchange="yourFunction()" multiple/>
                    <!-- won't be cleared -->
                    <input type="file" onchange="yourFunction()"/>
                    

                    Reference

                    【讨论】:

                      【解决方案14】:

                      您可以简单地将每次用户单击控件时的文件路径设置为null。现在,即使用户选择了同一个文件,onchange 事件也会被触发。

                      <input id="file" onchange="file_changed(this)" onclick="this.value=null;" type="file" accept="*/*" />
                      

                      【讨论】:

                      • 我需要这样的解决方案。它真的很短,可以完成工作。 Mariusz Wiazowski 的想法很好。
                      • 其他解决方案是在输入标签更改时更改值。但是我们不希望在选择文件后更改该值。
                      • 酷,比在 dom 中再次删除和添加元素要好得多,谢谢
                      【解决方案15】:

                      您可以使用form.reset() 清除文件输入的files 列表。 这会将所有字段重置为默认值,但在许多情况下,您可能只在表单中使用输入 type='file' 来上传文件。 在此解决方案中,无需克隆元素并再次重新挂钩事件。

                      感谢philiplehmann

                      【讨论】:

                        【解决方案16】:

                        如果你不想使用 jQuery

                        <form enctype='multipart/form-data'>
                            <input onchange="alert(this.value); return false;" type='file'>
                            <br>
                            <input type='submit' value='Upload'>
                        </form>
                        

                        它在 Firefox 中运行良好,但对于 Chrome,您需要在警报后添加 this.value=null;

                        【讨论】:

                          【解决方案17】:

                          如果您尝试过.attr("value", "") 并没有成功,请不要惊慌(就像我一样)

                          改用.val(""),就可以了

                          【讨论】:

                            【解决方案18】:

                            这对我有用

                            <input type="file" onchange="function();this.value=null;return false;">
                            

                            【讨论】:

                            • 我猜你的意思是 function() { this.value = null;返回假; }
                            【解决方案19】:

                            我通过清除文件输入值 onClick 然后发布文件 onChange 来实现此功能。这允许用户连续两次选择同一个文件,并且仍然让更改事件触发以发布到服务器。我的示例使用the jQuery form plugin

                            $('input[type=file]').click(function(){
                                $(this).attr("value", "");
                            })  
                            $('input[type=file]').change(function(){
                                $('#my-form').ajaxSubmit(options);      
                            })
                            

                            【讨论】:

                            • onClickonChange 之前触发,所以这种方法对我来说很有效。
                            • 对于 jQuery 2.2.4,我必须使用 $(this).val("");
                            【解决方案20】:

                            你不能在这里触发change(正确的行为,因为没有任何改变)。但是,您也可以绑定 click...虽然这可能会经常触发 ...不过两者之间没有太多的中间地带。

                            $("#fileID").bind("click change", function() {
                              //do stuff
                            });
                            

                            【讨论】:

                            • 看来你只是在重复他的话,.click() 不是“重新选择时触发”。
                            • @BrunoLM - 不,这不是......但我认为你阅读了我说你不能这样做的部分,click 尽可能接近。
                            猜你喜欢
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 2013-12-29
                            • 2016-09-09
                            • 1970-01-01
                            • 1970-01-01
                            相关资源
                            最近更新 更多