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

Posted

技术标签:

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

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

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

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

我该怎么做?

【问题讨论】:

【参考方案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 API 和JS 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 尽可能接近。

以上是关于如何检测同一文件的输入类型=文件“更改”?的主要内容,如果未能解决你的问题,请参考以下文章

在输入类型=“文件”上更改光标类型 [重复]

如何使用 Jest/Enzyme 在 React 中测试文件类型输入的更改处理程序?

如何在表单的输入类型=“文件”中添加图像并将它们都提交到同一个表单后生成缩略图

如何允许输入类型=文件在反应组件中选择相同的文件

为啥输入类型 = 文件的更改没有用 `form.serialize()` 标识

为啥 iPhone 的 Safari 不触发输入类型 = 文件的更改事件?