102

How can someone limit the files that can be selected with the input type="file" element by extensions?

I already know the accept attribute, but in chrome it does limit the files by the last MIME Type defined (in this case "gif") and FF4 does not even limit anything.

<input type="file" accept="image/jpg, image/gif">

Am I doing anything wrong or is there another way?

Willi Mentzel
  • 21,499
  • 16
  • 88
  • 101
haemse
  • 3,079
  • 4
  • 25
  • 38

4 Answers4

286

Easy way of doing it would be:

<input type="file" accept=".gif,.jpg,.jpeg,.png,.doc,.docx">

Works with all browsers, except IE9. I haven't tested it in IE10+.

Edi Budimilic
  • 3,609
  • 2
  • 16
  • 20
  • 1
    `accept` does not work in Firefox (as of 31.0 and 32.0) – GeriBoss Sep 10 '14 at 07:37
  • 2
    Test in FF 37.0. Works fine!. – mggSoft Jun 01 '15 at 15:52
  • this seems perfectly valid according to the [MDN docs](https://developer.mozilla.org/en/docs/Web/HTML/Element/Input) – Liam Jun 10 '15 at 12:30
  • 3
    Under the "accept" of a file input, there can also be a definition of the general type of the files for selection. For example, if you put "image/*" under the "accept" attribute, the limitation will cover all the standard file formats (gif, jpeg and so on) for images and not just the type(s) by extensions. In addition, you can combine the pre-defined type(s) and extensions. For example: "image/*,.swf". For this example, the limitation will include all standard image files AND all ".swf" files. NOTE: the user can always select "All Files" from the type list in the dialog box... ;-) – TheCuBeMan Apr 19 '16 at 15:23
  • 1
    This helps to provide some filtering to the file dialog on uploads, but I definitely think this needs to be used in conjunction with a server restriction too. – jaseeey Jun 28 '16 at 10:45
  • tanks ,its work with Firefox 57.0.4 (64-bit) – sirmagid Jan 05 '18 at 07:07
  • i beliefe the user can forge his own post-method, bypassing your accept. this looks nice at first sight, but safer is always cheking @ serverside – clockw0rk Sep 18 '18 at 15:30
  • 2
    @clockw0rk input check and security should always be implemented on the server side. The accept feature exists only to help users quickly filter relevant files and not having to sift through thousands of irrelevant files. – anneb Dec 07 '20 at 19:12
27

NOTE: This answer is from 2011. It was a really good answer back then, but as of 2015, native HTML properties are supported by most browsers, so there's (usually) no need to implement such custom logic in JS. See Edi's answer and the docs.


Before the file is uploaded, you can check the file's extension using Javascript, and prevent the form being submitted if it doesn't match. The name of the file to be uploaded is stored in the "value" field of the form element.

Here's a simple example that only allows files that end in ".gif" to be uploaded:

<script type="text/javascript">
    function checkFile() {
        var fileElement = document.getElementById("uploadFile");
        var fileExtension = "";
        if (fileElement.value.lastIndexOf(".") > 0) {
            fileExtension = fileElement.value.substring(fileElement.value.lastIndexOf(".") + 1, fileElement.value.length);
        }
        if (fileExtension.toLowerCase() == "gif") {
            return true;
        }
        else {
            alert("You must select a GIF file for upload");
            return false;
        }
    }
</script>

<form action="upload.aspx" enctype="multipart/form-data" onsubmit="return checkFile();">
    <input name="uploadFile" id="uploadFile" type="file" />

    <input type="submit" />
</form>

However, this method is not foolproof. Sean Haddy is correct that you always want to check on the server side, because users can defeat your Javascript checking by turning off javascript, or editing your code after it arrives in their browser. Definitely check server-side in addition to the client-side check. Also I recommend checking for size server-side too, so that users don't crash your server with a 2 GB file (there's no way that I know of to check file size on the client side without using Flash or a Java applet or something).

However, checking client side before hand using the method I've given here is still useful, because it can prevent mistakes and is a minor deterrent to non-serious mischief.

Community
  • 1
  • 1
Joshua Carmody
  • 12,581
  • 15
  • 63
  • 81
  • 1
    This is the best answer. Even though it's understood that you definitely need to check files properly on the server side, this client side JS check is good for usability - means you can warn the user early of a probable error. – Daniel Howard Nov 25 '13 at 12:31
  • 3
    you're gonna want to have a toLowerCase() in there before the comparison – MrTristan Dec 05 '14 at 17:40
  • @MrTristan Good suggestion. I've added it. – Joshua Carmody Jun 12 '15 at 02:17
  • With IE You can check the file size using the Scripting.FileSystemObject but you need to allow for unsafe ActiveX in the client browser. So yes there is no "good" way. – sproketboy Jan 27 '17 at 19:14
14

Honestly, the best way to limit files is on the server side. People can spoof file type on the client so taking in the full file name at server transfer time, parsing out the file type, and then returning a message is usually the best bet.

Sean Haddy
  • 1,545
  • 1
  • 14
  • 19
  • 7
    +1. Also I recommend putting something in your server side code to stop the upload if the received file is too large. – Joshua Carmody Apr 26 '11 at 21:32
  • thx ... i made it serversided. – haemse May 16 '11 at 22:12
  • @JoshuaCarmody how do you suggest to do it for large files(2gb and above) on server side? – Allan Chua Oct 17 '13 at 04:58
  • 1
    @Allan Depends a lot on the tech. ASP.NET has a "max request size" that you can specify in the Web.config. Writing a handler that reads the request from an input stream and stops after a certain number of bytes is possible in other languages. Really depends on your app. Post a separate question if you'd like more details. – Joshua Carmody Oct 18 '13 at 19:55
  • 1
    +1, but note: this answer is vaguely stale, since the HTML5 File API allows more file work to be done client side. I, for example, am not sending the file upstream, I'm loading the text into a textarea. The fact remains, that the server should be vigilant any time it receives a file. – Chris Pfohl Apr 28 '14 at 14:30
  • 20
    I think it's better to do both. Giving the user feedforward about the files that are(n't) selectable, will save some frustrations. Because if the users spends half a minute precisely selecting files he needs, and afterwards finds out it's all for nothing.. The earlier you can tel hem, the better. – Pepijn Gieles Jan 12 '15 at 08:13
  • 5
    -1. Good suggestion, but the question didn't suggest the files would be uploaded anywhere. It didn't even suggest the presence of a server at all (such as in the case of a fully client-side app). As said already, this answer should be a comment instead. – John Weisz Dec 28 '18 at 16:59
  • Serverside is good, but also means the file got sent to server already, your wasting time and traffic if you can easily prevent on the client. Better to have some client side validation as well – yeahdixon Apr 15 '19 at 17:34
  • What if you want to show error before uploading? Checking on server is a must but preventing from client could be good for user experience – thepowerlies Sep 08 '20 at 10:41
1
 function uploadFile() {
     var fileElement = document.getElementById("fileToUpload");
        var fileExtension = "";
        if (fileElement.value.lastIndexOf(".") > 0) {
            fileExtension = fileElement.value.substring(fileElement.value.lastIndexOf(".") + 1, fileElement.value.length);
        }
        if (fileExtension == "odx-d"||fileExtension == "odx"||fileExtension == "pdx"||fileExtension == "cmo"||fileExtension == "xml") {
         var fd = new FormData();
        fd.append("fileToUpload", document.getElementById('fileToUpload').files[0]);
        var xhr = new XMLHttpRequest();
        xhr.upload.addEventListener("progress", uploadProgress, false);
        xhr.addEventListener("load", uploadComplete, false);
        xhr.addEventListener("error", uploadFailed, false);
        xhr.addEventListener("abort", uploadCanceled, false);
        xhr.open("POST", "/post_uploadReq");
        xhr.send(fd);
        }
        else {
            alert("You must select a valid odx,pdx,xml or cmo file for upload");
            return false;
        }
       
      }

tried this , works very well

Community
  • 1
  • 1
prajwal
  • 11
  • 1
  • 1
    If you are uploading files, remember to also validate file types on the server, as client-side validation can be bypassed. – John Weisz Dec 28 '18 at 17:03