如何检测同一文件的输入类型=文件“更改”?


131

我想在用户选择文件时触发一个事件。.change如果用户每次都更改文件,则事件将起作用。

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

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

我该怎么做?

Answers:


78

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

jsFiddle上的示例。

或者您可以简单地使用.prop("value", ""),请参见jsFiddle上的此示例

  • jQuery 1.6以上 prop
  • 早期版本 attr

@Pekka:不完全是。但是他可以适应它。假设他需要发布文件。发布后,他可以调用js函数,该函数将删除并添加新的文件选择器。这是可行的。
BrunoLM 2010年

3
请注意,当您使用.attr("value", "").val("")(如下面@ wagner-leonardi的建议)时,Internet Explorer将触发更改事件,而chrome则不
触发

4
由于“值”是输入的属性,而不是输入的属性,因此建议的jQuery用法为.prop("value", "")
Roger Barreto


49

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

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

2
我需要这样的解决方案。它真的很短,可以完成工作。马里乌斯·维阿佐夫斯基(Mariusz Wiazowski)好主意。
Jay Dharmendra Solanki '18

其他解决方案是在输入标签更改时更改值。但是,我们不希望在选择文件后更改该值。
songgeb

1
很酷,比再次删除并在dom中添加元素更好的方式,谢谢
David Dal Busco

24

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

17

我通过清除文件输入值onClick然后发布文件onChange来使其工作。这样,用户可以连续两次选择相同的文件,并且仍然可以触发change事件发送到服务器。我的示例使用jQuery表单插件

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

onClick在之前触发onChange,因此此方法对我非常有用。
iplus26 '17

8

这对我有用

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

1
我猜你的意思是像function(){this.value = null; 返回false;}
Jacek Pietal

7

VueJs解决方案

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

1
感谢您提出的变化答案
Coisox

5

来自@braitsch的启发,我在AngularJS2中使用了以下内容 input-file-component

<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)救了我:-)


3

您可能最容易做的就是将值设置为空字符串。即使再次选择同一文件,这也会强制其每次“更改”文件。

<input type="file" value="" />


3

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

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


2

如果您不想使用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;在警报后添加。


2

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

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

参考


1

您不能在change此处开火(正确的行为,因为没有任何更改)。但是,您也可以绑定click...虽然这可能触发得太多 ...但是两者之间没有太多中间立场。

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

看来您只是在重复他的话,.click()而不是在“重选时开火”。
BrunoLM

@BrunoLM-不,不是。。。但是,我想你读了我说你做不到的那部分,它click已经接近了。
尼克·克雷弗

1

为输入创建单击事件和更改事件。单击事件将清空输入,更改事件包含您要执行的代码。

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

$("#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>


0

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

感谢philiplehmann


0

我遇到了同样的问题,我在上面的解决方案中加了红色,但是他们没有得到任何很好的解释,说明真正发生了什么。

我写的这个解决方案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>

0

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

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

https://www.html5rocks.com/zh-CN/tutorials/file/dndfiles/

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

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

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


0

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

// 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;
};

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.