328

Is there any chance to detect every file selection the user made for an HTML input of type file element?

This was asked many times before, but the usually proposed onchange event doesn't fire if the user select the same file again.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
dronus
  • 10,774
  • 8
  • 54
  • 80
  • 7
    Would your code then also have to fire if the user hits Cancel then? One expects that hitting Cancel will do nothing, and I think most users would further expect that re-selecting the same file would have the same effect as Cancel. I don't know if this is possible or not but I suggest you reconsider this design anyway. – KRyan Aug 19 '12 at 23:10
  • 4
    On cancel it should not fire or make it otherwise detectable. It is more meant to remove an UI ceveat: If some action is invoked after the file is choosen, the user usually expect the action to repeat if he choose the file again. – dronus Aug 19 '12 at 23:48
  • Maybe we can have this behaviour if we set the `input`s value to '' after doing something with the file. But that would remove the visible filename too. However, that may be ok, as the file is actually processed and the result of that action may appear somewhere else. – dronus Aug 19 '12 at 23:52
  • Plz Explain the Que What you want to do? – GajendraSinghParihar Aug 22 '12 at 06:34
  • related: [Capturing the close of the open-file-dialog with JavaScript](http://stackoverflow.com/q/12081493/1048572) – Bergi Aug 23 '12 at 00:32
  • Have you tried the jquery trigger to fire it again – Hello-World Aug 23 '12 at 06:23
  • 2
    All I want is to simulate the old school behaviour desktop applications have. If I 'open' the same file again in an desktop application, it is usually reloaded, or if some action is done with the file (like converting it so another format for example) this action is done again. This is what desktop users may expect from a web app too, but the `file` input `onchange` event doesn't resemble. – dronus Aug 24 '12 at 19:59

11 Answers11

421

Set the value of the input to null on each onclick event. This will reset the input's value and trigger the onchange event even if the same path is selected.

var input = document.getElementsByTagName('input')[0];

input.onclick = function () {
  this.value = null;
};
  
input.onchange = function () {
  console.log(this.value);
};
<input type="file" value="C:\fakepath">

Note: It's normal if your file is prefixed with 'C:\fakepath'. That's a security feature preventing JavaScript from knowing the file's absolute path. The browser still knows it internally.

Paolo Moretti
  • 54,162
  • 23
  • 101
  • 92
Brian Ustas
  • 62,713
  • 3
  • 28
  • 21
  • 2
    I tried the demo, but (using Chrome 21) I keep getting `C:\fakepath\` + then the filename I selected (excluding the path). The alert is show on every select of the same file though. – Jasper de Vries Aug 24 '12 at 15:16
  • 1
    @JasperdeVries That's a security feature preventing JavaScript from knowing a file's absolute path. The browser still knows the path internally. – Brian Ustas Aug 24 '12 at 15:38
  • 1
    As an aside, null is the only permitted value for . So if you're trying to set it to undefined and getting an exception then that's the reason why. – Zephyr was a Friend of Mine Nov 14 '13 at 10:17
  • 5
    It doesn't work well in IE11 unless you make a small change: [demo](http://jsfiddle.net/scMF6/2/). –  Jun 08 '14 at 09:31
  • 41
    It's better to put `this.value = null` at the end of the `onchange` because it's possible to active an input element without clicking on it (by using the keyboard). You can store `input.files` if you need to reference it later. – Halcyon Oct 10 '14 at 13:19
  • Setting `this.value == null` worked for me. The change event was being triggered when I click the input button but without selecting a file. Thanks! – yuva Jun 19 '15 at 08:46
  • Worked for me too. I needed to do the same thing in Vue JS. – Piyush Beli Apr 04 '19 at 12:45
  • 1
    The problem with this approach is that if you then cancel the file selection, the file you previously had selected will now have been lost. – lukens Jun 04 '20 at 11:17
  • The value should be set to an empty string since the type of `this.value` is a `string`. setting it to `null` will result in a Typescript error. I also agree with @Halcyon this cleanup should be handled in the onChange event. – Daniel Aviv Aug 26 '22 at 22:04
  • I had a similar problem in Blazor's component. When opening the file selection dialog and NOT choosing any file, none of OnChange, onchange or oninput events were firing. On the standard HTML however these (onchange and oninput) fired regardless of whether I selected a file or not. I employed OnClick(which was firing every time of course) and reset my "value" variable. Problem solved. Thanx! – Pap Oct 12 '22 at 10:10
52

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 = ''
}
Rosy Shrestha
  • 1,359
  • 10
  • 10
28
<form enctype='multipart/form-data'>
    <input onchange="alert(this.value); this.value=null; return false;" type='file'>
    <br>
    <input type='submit' value='Upload'>
</form>

this.value=null; is only necessary for Chrome, Firefox will work fine just with return false;

Here is a FIDDLE

elshnkhll
  • 2,077
  • 1
  • 19
  • 24
10
handleChange({target}) {
    const files = target.files
    target.value = ''
}
4b0
  • 21,981
  • 30
  • 95
  • 142
Shashwat Gupta
  • 5,071
  • 41
  • 33
  • 2
    Hey ngCourse ! Code-only answers may solve the problem but they are much more useful if you explain how they solve it. Community requires theory as well as code both to understand your answer fully. – RBT Mar 30 '20 at 00:57
  • While this code may solve the question, [including an explanation](//meta.stackexchange.com/q/114762) of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please [edit] your answer to add explanations and give an indication of what limitations and assumptions apply. [From Review](/review/low-quality-posts/25719417) – double-beep Mar 30 '20 at 07:05
  • Yes, This worked. But as @double-beep said, you should explain the answer. And thanks btw – HV Sharma Jul 23 '20 at 05:53
9

In this article, under the title "Using form input for selecting"

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

<input type="file" id="files" name="files[]" multiple />

<script>
function handleFileSelect(evt) {

    var files = evt.target.files; // FileList object

    // files is a FileList of File objects. List some properties.
    var output = [];
    for (var i = 0, f; f = files[i]; i++) {
     // Code to execute for every file selected
    }
    // Code to execute after that

}

document.getElementById('files').addEventListener('change', 
                                                  handleFileSelect, 
                                                  false);
</script>

It adds an event listener to 'change', but I tested it and it triggers even if you choose the same file and not if you cancel.

andrewsi
  • 10,807
  • 132
  • 35
  • 51
  • Considering the potentially ambiguous meaning of "change" in this case, did you try this in multiple browsers? You may want to specify which ones you tried it on as on the web, browsers aren't exactly always in consensus about these things. – Vala Aug 24 '12 at 14:24
  • 2
    What environment you use for your test? My experience with Chrome was the one I stated in the question, the `change` event would fire only on filename changes. – dronus Aug 24 '12 at 20:02
2
<input #myInput type="file" id="imgFile" (click)="$event.target.value=null"
       (change)="detectUploadedImage($event)" accept="image/*" />
Slava Rozhnev
  • 9,510
  • 6
  • 23
  • 39
1

Clearing the value of 0th index of input worked for me. Please try the below code, hope this will work (AngularJs).

          scope.onClick = function() {
            input[0].value = "";
                input.click();
            };
1

Usage of two way binding worked for me if you are working with Angular.

Here is my HMTL

<input type="file" #upload name="upload" [(ngModel)]="inputValue"(change)='fileEvent($event)'/>

and TS..

  @ViewChild('upload') uploadBtn: HTMLElement;

  fileEvent(e: any){
    
   //file upload part... 

    this.inputValue = "";
  }
1

The selected answer (using state to set input value null) gave me an error.

I use empty strings instead

    const [fileValue, setFileValue] = React.useState("")

    <input
        onClick={() => {
           setFileValue("");
        }}
        type="file"
        value={fileValue}
        onChange={handleAddFile}
    />


Jar
  • 1,766
  • 1
  • 21
  • 27
0

Do whatever you want to do after the file loads successfully.just after the completion of your file processing set the value of file control to blank string.so the .change() will always be called even the file name changes or not. like for example you can do this thing and worked for me like charm

   $('#myFile').change(function () {
       LoadFile("myFile");//function to do processing of file.
       $('#myFile').val('');// set the value to empty of myfile control.
    });
0

I can't use javascript in the project i'm working on.

Simply used:

<input type="file" onclick="this.value = null;" ..>
metamagikum
  • 1,307
  • 15
  • 19