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

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

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

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

我该怎么做?

153635 次浏览

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

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

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

关于JSFiddle的示例.

或者,您可以简单地使用.prop("value", ""),请参阅JSFiddle上的这个例子

  • jQuery 1.6+prop
  • 早期版本attr

我通过清除文件输入值onclick,然后发布文件onchange来实现这一点。这允许用户连续两次选择相同的文件,并且仍然触发更改事件以发布到服务器。我的示例使用jQuery表单插件

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

这对我有用。

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

如果您已尝试.attr("value", ""),但不起作用,请不要惊慌(就像我一样)

只需执行.val(""),即可正常工作

如果您不想使用jQuery

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

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

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

感谢菲利普尔曼

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

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

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

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

参考文献

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

https://jsfiddle.net/r2wjp6u8/编写的这个解决方案不会在DOM树中做很多更改,它只是更改输入字段的值。从性能方面来说,它应该更好一点。

链接至FIDICH: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>

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

你与文件交互的方式(当用户“上传”文件时JS所做的)是HTML5文件APIJS文件阅读器

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 ”的函数,该函数将读取->存储->将当前文件的元数据与以前的文件进行比较。然后,您可以在选择所需的文件时触发事件。

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

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

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

受到@Braitsch的启发,我在我的AngularJS2input-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)拯救了我:-)

Vuejs解决方案

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

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

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

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

为输入创建一个单击事件和一个更改事件。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>

下面是我找到的适合我的反应方式解决方案:

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

最简单的方法是直接在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 = ""
}

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

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

与Angular 11相同的问题。我需要显示已下载文件的列表。一旦进入列表,就可以删除这些文件。所以我不能删除一个文件,然后直接重新上传,或者连续几次上传同一个文件。

上一个代码:https://stackblitz.com/edit/angular-bxpsgn?file=src/app/app.component.ts

我在输入文件中添加了一个控制器,并在上传文件时重置其值,从而解决了这个问题。我只需要通过输入的引用来获取文件,因为输入的值是上传文件的路径。

固定代码:https://stackblitz.com/edit/angular-ivy-noynch?file=src/app/app.component.ts

如果您正在使用React,只需添加一个键即可解决此问题。

let uid = 0;


function Example() {
const [fileState, setFileState] = useState({
key: uid,
});


function handleChangeSelectFile() {
setFileState({
key: ++uid,
})
}


return (
<input
type="file"
accept="image/jpeg,image/png"
key={fileState.key}
onChange={handleChangeSelectFile}
/>
)
}