How to detect input type=file "change" for the same file?

JqueryHtmlEventsCross Browser

Jquery Problem Overview


I want to fire an event when the user select a file. Doing so with .change event it works if the user changes the file every time.

But I want to fire the event if the user select the same file again.

  1. User select file A.jpg (event fires)
  2. User select file B.jpg (event fires)
  3. User select file B.jpg (event doesn't fire, I want it to fire)

How can I do it?

Jquery Solutions


Solution 1 - Jquery

You can trick it. Remove the file element and add it in the same place on change event. It will erase the file path making it changeable every time.

Example on jsFiddle.

Or you can simply use .prop("value", ""), see this example on jsFiddle.

  • jQuery 1.6+ prop

  • Earlier versions attr

Solution 2 - Jquery

You can simply set to null the file path every time user clicks on the control. Now, even if the user selects the same file, the onchange event will be triggered.

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

Solution 3 - Jquery

If you have tried .attr("value", "") and didn't work, don't panic (like I did)

just do .val("") instead, and will work fine

Solution 4 - Jquery

Use onClick event to clear value of target input, each time user clicks on field. This ensures that the onChange event will be triggered for the same file as well. Worked for me :)

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

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

Using TypeScript

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

Solution 5 - Jquery

I got this to work by clearing the file input value onClick and then posting the file onChange. This allows the user to select the same file twice in a row and still have the change event fire to post to the server. My example uses the the jQuery form plugin.

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

Solution 6 - Jquery

Here's the React-y way solution i've found that worked for me:

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

Solution 7 - Jquery

VueJs solution

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

Solution 8 - Jquery

This work for me

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

Solution 9 - Jquery

Inspiring from @braitsch I have used the following in my 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);
    }
}

Here the onClick(event) rescued me :-)

Solution 10 - Jquery

Probably the easiest thing you can do is set the value to an empty string. This forces it to 'change' the file each time even if the same file is selected again.

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

Solution 11 - Jquery

Create for the input a click event and a change event. The click event empties the input and the change event contains the code you want to execute.

So the click event will empty when you click the input button(before the select file windows opens), therefor the change event will always trigger when you select a file.

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

Solution 12 - Jquery

The simplest way would be to set the input value to an empty string directly in the change or input event, which one mostly listens to anyways.

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

Solution 13 - Jquery

Depending on the type of event being fired, for React you may need to adjust the solution to:

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

Solution 14 - Jquery

If you don't want to use jQuery

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

It works fine in Firefox, but for Chrome you need to add this.value=null; after alert.

Solution 15 - Jquery

By default, the value property of input element cleared after selection of files if the input have multiple attributes. If you do not clean this property then "change" event will not be fired if you select the same file. You can manage this behavior using multiple attribute.

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

Reference

Solution 16 - Jquery

Same issue with Angular 11. I needed to display a list of downloaded files. Once in the list, these files can be deleted. So I couldn't delete a file and re-upload it directly or upload the same file several times in a row.

Previous code: https://stackblitz.com/edit/angular-bxpsgn?file=src/app/app.component.ts

I solved the issue by adding a controller to the input file and resetting its value when a file is uploaded. I just had to fetch the files via the reference of the input, as the value of the input is the path of the uploaded files.

Fixed code : https://stackblitz.com/edit/angular-ivy-noynch?file=src/app/app.component.ts

Solution 17 - Jquery

You can't make change fire here (correct behavior, since nothing changed). However, you could bind click as well...though this may fire too often...there's not much middle ground between the two though.

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

Solution 18 - Jquery

You can use form.reset() to clear the file input's files list. This will reset all fields to default values, but in many cases you may be only using the input type='file' in a form to upload files anyway. In this solution there is no need to clone the element and re-hook events again.

Thanks to [philiplehmann][1]

[1]: https://github.com/philiplehmann "philiplehmann"

Solution 19 - Jquery

I ran into same issue, i red through he solutions above but they did not get any good explanation what was really happening.

This solution i wrote https://jsfiddle.net/r2wjp6u8/ does no do many changes in the DOM tree, it just changes values of the input field. From performance aspect it should be bit better.

Link to fiddle: 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>

Solution 20 - Jquery

So, there is no way to 100% be sure they are selecting the same file unless you store each file and compare them programmatically.

The way you interact with files (what JS does when the user 'uploads' a file) is HTML5 File API and 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

These tutorials show you how to capture and read the metadata (stored as js object) when a file is uploaded.

Create a function that fires 'onChange' that will read->store->compare metadata of the current file against the previous files. Then you can trigger your event when the desired file is selected.

Solution 21 - Jquery

Believe me, it will definitely help you!

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

Hope this will help many of you guys.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGadonskiView Question on Stackoverflow
Solution 1 - JqueryBrunoLMView Answer on Stackoverflow
Solution 2 - JqueryMariusz WiazowskiView Answer on Stackoverflow
Solution 3 - JqueryWagner LeonardiView Answer on Stackoverflow
Solution 4 - JqueryRosy ShresthaView Answer on Stackoverflow
Solution 5 - JquerybraitschView Answer on Stackoverflow
Solution 6 - JqueryHeckmannView Answer on Stackoverflow
Solution 7 - JqueryMicheal C WallasView Answer on Stackoverflow
Solution 8 - Jqueryuser2678106View Answer on Stackoverflow
Solution 9 - JqueryMKJView Answer on Stackoverflow
Solution 10 - JqueryCurtView Answer on Stackoverflow
Solution 11 - Jqueryhoi jaView Answer on Stackoverflow
Solution 12 - JqueryKevin KrepsView Answer on Stackoverflow
Solution 13 - JqueryCarolynView Answer on Stackoverflow
Solution 14 - JqueryelshnkhllView Answer on Stackoverflow
Solution 15 - JqueryPulkit AggarwalView Answer on Stackoverflow
Solution 16 - JqueryAntoine BraunView Answer on Stackoverflow
Solution 17 - JqueryNick CraverView Answer on Stackoverflow
Solution 18 - JqueryRui NunesView Answer on Stackoverflow
Solution 19 - JqueryBallpinView Answer on Stackoverflow
Solution 20 - JqueryStephanie SchellinView Answer on Stackoverflow
Solution 21 - JqueryArifMustafaView Answer on Stackoverflow