Hoe kan ik bestandsextensies krijgen met JavaScript?

Zie code:

var file1 = "50.xsl";
var file2 = "30.doc";
getFileExtension(file1); //returns xsl
getFileExtension(file2); //returns doc
function getFileExtension(filename) {
    /*TODO*/
}

Antwoord 1, autoriteit 100%

Nieuwere bewerking:er zijn veel dingen veranderd sinds deze vraag voor het eerst werd gepost – er is veel echt goede informatie in het herziene antwoord van Wallaceren VisioN’s uitstekende overzicht


Bewerken:Gewoon omdat dit het geaccepteerde antwoord is; wallacer’s antwoordis inderdaad veel beter:

return filename.split('.').pop();

Mijn oude antwoord:

return /[^.]+$/.exec(filename);

Zou het moeten doen.

Bewerken:in reactie op de opmerking van PhiLho, gebruik zoiets als:

return (/[.]/.exec(filename)) ? /[^.]+$/.exec(filename) : undefined;

Antwoord 2, autoriteit 97%

return filename.split('.').pop();

Bewerken:

Dit is een andere niet-regex-oplossing waarvan ik denk dat deze efficiënter is:

return filename.substring(filename.lastIndexOf('.')+1, filename.length) || filename;

Er zijn enkele hoekgevallen die beter kunnen worden afgehandeld door het antwoord van VisioNhieronder, met name bestanden zonder extensie (.htaccessetc inbegrepen).

Het is zeer performant en behandelt hoekgevallen op een aantoonbaar betere manier door ""terug te geven in plaats van de volledige tekenreeks als er geen punt of geen tekenreeks voor de punt staat. Het is een zeer goed gemaakte oplossing, zij het moeilijk om te lezen. Plak het in je helpers-lib en gebruik het gewoon.

Oude bewerking:

Een veiligere implementatie als je bestanden tegenkomt zonder extensie, of verborgen bestanden zonder extensie (zie VisioN’s commentaar op Tom’s antwoord hierboven) zou zoiets zijn

var a = filename.split(".");
if( a.length === 1 || ( a[0] === "" && a.length === 2 ) ) {
    return "";
}
return a.pop();    // feel free to tack .toLowerCase() here if you want

Als a.lengther één is, is het een zichtbaar bestand zonder extensie dwz. bestand

Als a[0] === ""en a.length === 2het een verborgen bestand is zonder extensie, dwz. .htaccess

Ik hoop dat dit helpt om problemen met de iets complexere zaken op te lossen. Qua prestaties denk ik dat deze oplossing in de meeste browsers een beetje langzamer is dan regex. Voor de meest voorkomende doeleinden zou deze code echter perfect bruikbaar moeten zijn.


Antwoord 3, autoriteit 34%

De volgende oplossing is snelen kortgenoeg om in bulkbewerkingen te gebruiken en extra bytes te besparen:

return fname.slice((fname.lastIndexOf(".") - 1 >>> 0) + 2);

Hier is nog een eenregelige, niet-regexp universele oplossing:

return fname.slice((Math.max(0, fname.lastIndexOf(".")) || Infinity) + 1);

Beide werken correct met namen zonder extensie (bijv. mijnbestand) of beginnend met .punt (bijv. .htaccess):

""                            -->   ""
 "name"                        -->   ""
 "name.txt"                    -->   "txt"
 ".htpasswd"                   -->   ""
 "name.with.many.dots.myext"   -->   "myext"

Als je om de snelheid geeft, kun je de benchmarkgebruiken en controleer of de aangeboden oplossingen de snelste zijn, terwijl de korte enorm snel is:

Hoe de korte werkt:

  1. String.lastIndexOfmethode retourneert de laatste positie van de substring (dwz ".") in de gegeven string (dwz fname). Als de subtekenreeks niet wordt gevonden, retourneert de methode -1.
  2. De “onacceptabele” posities van punt in de bestandsnaam zijn -1en 0, die respectievelijk verwijzen naar namen zonder extensie (bijv. "name") en naar namen die beginnen met een punt (bijv. ".htaccess").
  3. Zero-fill rechter shift-operator(>>>) indien gebruikt met nul beïnvloedt negatieve getallen die -1omzetten in 4294967295en -2naar 4294967294, wat handig is om de bestandsnaam in de randgevallen ongewijzigd te laten (een soort truc hier).
  4. String.prototype.sliceextraheert het deel van de bestandsnaam uit de positie die werd berekend zoals beschreven. Als het positienummer langer is dan de lengte van de tekenreeks, retourneert de methode "".

Als je een duidelijkere oplossing wilt die op dezelfde manier werkt (plus met extra ondersteuning van het volledige pad), bekijk dan de volgende uitgebreide versie. Deze oplossing zal tragerzijn dan eerdere oneliners, maar is veel gemakkelijker te begrijpen.

function getExtension(path) {
    var basename = path.split(/[\\/]/).pop(),  // extract file name from full path ...
                                               // (supports `\\` and `/` separators)
        pos = basename.lastIndexOf(".");       // get last position of `.`
    if (basename === "" || pos < 1)            // if file name is empty or ...
        return "";                             //  `.` not found (-1) or comes first (0)
    return basename.slice(pos + 1);            // extract extension ignoring `.`
}
console.log( getExtension("/path/to/file.ext") );
// >> "ext"

Alle drie de varianten zouden in elke webbrowser aan de clientzijde moeten werken en kunnen ook worden gebruikt in de NodeJS-code aan de serverzijde.


Antwoord 4, autoriteit 4%

function getFileExtension(filename)
{
  var ext = /^.+\.([^.]+)$/.exec(filename);
  return ext == null ? "" : ext[1];
}

Getest met

"a.b"     (=> "b") 
"a"       (=> "") 
".hidden" (=> "") 
""        (=> "") 
null      (=> "")  

Ook

"a.b.c.d" (=> "d")
".a.b"    (=> "b")
"a..b"    (=> "b")

Antwoord 5, autoriteit 2%

function getExt(filename)
{
    var ext = filename.split('.').pop();
    if(ext == filename) return "";
    return ext;
}

Antwoord 6, autoriteit 2%

var extension = fileName.substring(fileName.lastIndexOf('.')+1);

Antwoord 7, autoriteit 2%

Er is hiervoor een standaard bibliotheekfunctie in de pathmodule:

import path from 'path';
console.log(path.extname('abc.txt'));

Uitvoer:

.txt

Dus, als je alleen het formaat wilt:

path.extname('abc.txt').slice(1) // 'txt'

Als er geen extensie is, retourneert de functie een lege string:

path.extname('abc') // ''

Als je Node gebruikt, is pathingebouwd. Als u zich op de browser richt, dan bundelt Webpack een path-implementatie voor u. Als u de browser zonder Webpack target, kunt u path-browserifyhandmatig opnemen.

Er is geen reden om strings te splitsen of regex te doen.


Antwoord 8

Als u te maken heeft met web-urls, kunt u het volgende gebruiken:

function getExt(filepath){
     return filepath.split("?")[0].split("#")[0].split('.').pop();
}
getExt("../js/logic.v2.min.js") // js
getExt("http://example.net/site/page.php?id=16548") // php
getExt("http://example.net/site/page.html#welcome.to.me") // html
getExt("c:\\logs\\yesterday.log"); // log

Demo: https://jsfiddle.net/squadjot/q5ard4fj/


Antwoord 9

var parts = filename.split('.');
return parts[parts.length-1];

Antwoord 10

function file_get_ext(filename)
    {
    return typeof filename != "undefined" ? filename.substring(filename.lastIndexOf(".")+1, filename.length).toLowerCase() : false;
    }

Antwoord 11

Code

/**
 * Extract file extension from URL.
 * @param {String} url
 * @returns {String} File extension or empty string if no extension is present.
 */
var getFileExtension = function (url) {
    "use strict";
    if (url === null) {
        return "";
    }
    var index = url.lastIndexOf("/");
    if (index !== -1) {
        url = url.substring(index + 1); // Keep path without its segments
    }
    index = url.indexOf("?");
    if (index !== -1) {
        url = url.substring(0, index); // Remove query
    }
    index = url.indexOf("#");
    if (index !== -1) {
        url = url.substring(0, index); // Remove fragment
    }
    index = url.lastIndexOf(".");
    return index !== -1
        ? url.substring(index + 1) // Only keep file extension
        : ""; // No extension found
};

Testen

Merk op dat als er geen zoekopdracht is, het fragment nog steeds aanwezig kan zijn.

"https://www.example.com:8080/segment1/segment2/page.html?foo=bar#fragment" --> "html"
"https://www.example.com:8080/segment1/segment2/page.html#fragment"         --> "html"
"https://www.example.com:8080/segment1/segment2/.htaccess?foo=bar#fragment" --> "htaccess"
"https://www.example.com:8080/segment1/segment2/page?foo=bar#fragment"      --> ""
"https://www.example.com:8080/segment1/segment2/?foo=bar#fragment"          --> ""
""                                                                          --> ""
null                                                                        --> ""
"a.b.c.d"                                                                   --> "d"
".a.b"                                                                      --> "b"
".a.b."                                                                     --> ""
"a...b"                                                                     --> "b"
"..."                                                                       --> ""

JSLint

0 waarschuwingen.


Antwoord 12

Snel en werkt correct met paden

(filename.match(/[^\\\/]\.([^.\\\/]+)$/) || [null]).pop()

Enkele randgevallen

/path/.htaccess => null
/dir.with.dot/file => null

Oplossingen die split gebruiken zijn traag en oplossingen met lastIndexOf behandelen geen randgevallen.


Antwoord 13

ik wilde dit gewoon delen.

fileName.slice(fileName.lastIndexOf('.'))

hoewel dit een nadeel heeft dat bestanden zonder extensie de laatste string teruggeven.
maar als je dit doet, zal dit alles oplossen:

  function getExtention(fileName){
     var i = fileName.lastIndexOf('.');
     if(i === -1 ) return false;
     return fileName.slice(i)
   }

Antwoord 14

// 获取文件后缀名
function getFileExtension(file) {
  var regexp = /\.([0-9a-z]+)(?:[\?#]|$)/i;
  var extension = file.match(regexp);
  return extension && extension[1];
}
console.log(getFileExtension("https://www.example.com:8080/path/name/foo"));
console.log(getFileExtension("https://www.example.com:8080/path/name/foo.BAR"));
console.log(getFileExtension("https://www.example.com:8080/path/name/.quz/foo.bar?key=value#fragment"));
console.log(getFileExtension("https://www.example.com:8080/path/name/.quz.bar?key=value#fragment"));

Antwoord 15

Ik weet zeker dat iemand mijn code in de toekomst kan en zal verkleinen en/of optimaliseren. Maar vanaf nuben ik er 200% zeker van dat mijn code in elke unieke situatie werkt (bijv. met alleen de alleen bestandsnaam, met relatieveem>, root-relativeen absoluteURL’s, met fragment#tags, met query?strings, en wat je er verder ook maar tegenaan gooit), foutloos en met uiterste precisie.

Ga voor bewijs naar: https://projects.jamesandersonjr.com/web/js_projects /get_file_extension_test.php

Hier is de JSFiddle: https://jsfiddle.net/JamesAndersonJr/ffcdd5z3/

Niet om overmoedig te zijn, of mijn eigen trompet te blazen, maar ik heb geen eencodeblok voor deze taak gezien (ik vond de ‘correcte’bestandsextensie, te midden van een reeks verschillende functioninvoerargumenten) die net zo goed werkt als dit.

Opmerking:Als een bestandsextensie niet bestaat voor de opgegeven invoertekenreeks, wordt eenvoudigweg een lege tekenreeks geretourneerd "", geen fout, noch een foutmelding.

Er zijn twee argumenten nodig:

  • String:fileNameOrURL(spreekt voor zich)

  • Boolean:showUnixDotFiles(Al dan niet om bestanden weer te geven die beginnen met een punt “.”)

Opmerking (2):als je mijn code leuk vindt, voeg hem dan toe aan je js-bibliotheek en/of repo’s, want ik heb hard gewerkt om hem te perfectioneren, en het zou jammer zijn verloren gaan. Dus, zonder verder oponthoud, hier is het:

function getFileExtension(fileNameOrURL, showUnixDotFiles)
    {
        /* First, let's declare some preliminary variables we'll need later on. */
        var fileName;
        var fileExt;
        /* Now we'll create a hidden anchor ('a') element (Note: No need to append this element to the document). */
        var hiddenLink = document.createElement('a');
        /* Just for fun, we'll add a CSS attribute of [ style.display = "none" ]. Remember: You can never be too sure! */
        hiddenLink.style.display = "none";
        /* Set the 'href' attribute of the hidden link we just created, to the 'fileNameOrURL' argument received by this function. */
        hiddenLink.setAttribute('href', fileNameOrURL);
        /* Now, let's take advantage of the browser's built-in parser, to remove elements from the original 'fileNameOrURL' argument received by this function, without actually modifying our newly created hidden 'anchor' element.*/ 
        fileNameOrURL = fileNameOrURL.replace(hiddenLink.protocol, ""); /* First, let's strip out the protocol, if there is one. */
        fileNameOrURL = fileNameOrURL.replace(hiddenLink.hostname, ""); /* Now, we'll strip out the host-name (i.e. domain-name) if there is one. */
        fileNameOrURL = fileNameOrURL.replace(":" + hiddenLink.port, ""); /* Now finally, we'll strip out the port number, if there is one (Kinda overkill though ;-)). */  
        /* Now, we're ready to finish processing the 'fileNameOrURL' variable by removing unnecessary parts, to isolate the file name. */
        /* Operations for working with [relative, root-relative, and absolute] URL's ONLY [BEGIN] */ 
        /* Break the possible URL at the [ '?' ] and take first part, to shave of the entire query string ( everything after the '?'), if it exist. */
        fileNameOrURL = fileNameOrURL.split('?')[0];
        /* Sometimes URL's don't have query's, but DO have a fragment [ # ](i.e 'reference anchor'), so we should also do the same for the fragment tag [ # ]. */
        fileNameOrURL = fileNameOrURL.split('#')[0];
        /* Now that we have just the URL 'ALONE', Let's remove everything to the last slash in URL, to isolate the file name. */
        fileNameOrURL = fileNameOrURL.substr(1 + fileNameOrURL.lastIndexOf("/"));
        /* Operations for working with [relative, root-relative, and absolute] URL's ONLY [END] */ 
        /* Now, 'fileNameOrURL' should just be 'fileName' */
        fileName = fileNameOrURL;
        /* Now, we check if we should show UNIX dot-files, or not. This should be either 'true' or 'false'. */  
        if ( showUnixDotFiles == false )
            {
                /* If not ('false'), we should check if the filename starts with a period (indicating it's a UNIX dot-file). */
                if ( fileName.startsWith(".") )
                    {
                        /* If so, we return a blank string to the function caller. Our job here, is done! */
                        return "";
                    };
            };
        /* Now, let's get everything after the period in the filename (i.e. the correct 'file extension'). */
        fileExt = fileName.substr(1 + fileName.lastIndexOf("."));
        /* Now that we've discovered the correct file extension, let's return it to the function caller. */
        return fileExt;
    };

Geniet! Je bent vrij welkom!:


Antwoord 16

Er is ook een eenvoudige aanpak met ES6-destructurering:

const path = 'hello.world.txt'
const [extension, ...nameParts] = path.split('.').reverse();
console.log('extension:', extension);

Antwoord 17

function extension(fname) {
  var pos = fname.lastIndexOf(".");
  var strlen = fname.length;
  if (pos != -1 && strlen != pos + 1) {
    var ext = fname.split(".");
    var len = ext.length;
    var extension = ext[len - 1].toLowerCase();
  } else {
    extension = "No extension found";
  }
  return extension;
}

//gebruik

extensie(‘file.jpeg’)

retourneert altijd de extensie lower cas, zodat u deze kunt controleren bij veldwijziging
werkt voor:

bestand.JpEg

bestand (geen extensie)

bestand. (geen extensie)


Antwoord 18

Probeer dit:

function getFileExtension(filename) {
  var fileinput = document.getElementById(filename);
  if (!fileinput)
    return "";
  var filename = fileinput.value;
  if (filename.length == 0)
    return "";
  var dot = filename.lastIndexOf(".");
  if (dot == -1)
    return "";
  var extension = filename.substr(dot, filename.length);
  return extension;
}

Antwoord 19

Als u op zoek bent naar een specifieke extensie en de lengte weet, kunt u substrgebruiken:

var file1 = "50.xsl";
if (file1.substr(-4) == '.xsl') {
  // do something
}

JavaScript-referentie:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr


Antwoord 20

“one-liner” om bestandsnaam en extensie te krijgen met reduceen array destructuring:

var str = "filename.with_dot.png";
var [filename, extension] = str.split('.').reduce((acc, val, i, arr) => (i == arr.length - 1) ? [acc[0].substring(1), val] : [[acc[0], val].join('.')], [])
console.log({filename, extension});

Antwoord 21

return filename.replace(/\.([a-zA-Z0-9]+)$/, "$1");

edit: Vreemd genoeg (of misschien niet) lijkt de $1in het tweede argument van de vervangmethode niet te werken… Sorry.


Antwoord 22

Ik realiseerde me net dat het niet genoeg is om commentaar te geven op het antwoord van p4bl0, hoewel Toms antwoord het probleem duidelijk oplost:

return filename.replace(/^.*?\.([a-zA-Z0-9]+)$/, "$1");

Antwoord 23

Voor de meeste toepassingen is een eenvoudig script zoals

return /[^.]+$/.exec(filename);

zou prima werken (zoals geleverd door Tom). Dit is echter niet onfeilbaar. Het werkt niet als de volgende bestandsnaam wordt opgegeven:

image.jpg?foo=bar

Het is misschien een beetje overdreven, maar ik raad aan om een url-parser zoals dezete gebruiken om te voorkomen dat storing door onvoorspelbare bestandsnamen.

Met die specifieke functie zou je de bestandsnaam als volgt kunnen krijgen:

var trueFileName = parse_url('image.jpg?foo=bar').file;

Hiermee wordt “image.jpg” uitgevoerd zonder de url vars. Dan bent u vrij om de bestandsextensie te pakken.


Antwoord 24

function func() {
  var val = document.frm.filename.value;
  var arr = val.split(".");
  alert(arr[arr.length - 1]);
  var arr1 = val.split("\\");
  alert(arr1[arr1.length - 2]);
  if (arr[1] == "gif" || arr[1] == "bmp" || arr[1] == "jpeg") {
    alert("this is an image file ");
  } else {
    alert("this is not an image file");
  }
}

Antwoord 25

Ik ben veel manen te laat voor het feest, maar voor de eenvoud gebruik ik zoiets als dit

var fileName = "I.Am.FileName.docx";
var nameLen = fileName.length;
var lastDotPos = fileName.lastIndexOf(".");
var fileNameSub = false;
if(lastDotPos === -1)
{
    fileNameSub = false;
}
else
{
    //Remove +1 if you want the "." left too
    fileNameSub = fileName.substr(lastDotPos + 1, nameLen);
}
document.getElementById("showInMe").innerHTML = fileNameSub;
<div id="showInMe"></div>

Antwoord 26

Een éénregelige oplossing die ook rekening houdt met queryparameters en eventuele tekens in url.

string.match(/(.*)\??/i).shift().replace(/\?.*/, '').split('.').pop()
// Example
// some.url.com/with.in/&ot.s/files/file.jpg?spec=1&.ext=jpg
// jpg

Antwoord 27

Deze eenvoudige oplossing

function extension(filename) {
  var r = /.+\.(.+)$/.exec(filename);
  return r ? r[1] : null;
}

Testen

/* tests */
test('cat.gif', 'gif');
test('main.c', 'c');
test('file.with.multiple.dots.zip', 'zip');
test('.htaccess', null);
test('noextension.', null);
test('noextension', null);
test('', null);
// test utility function
function test(input, expect) {
  var result = extension(input);
  if (result === expect)
    console.log(result, input);
  else
    console.error(result, input);
}
function extension(filename) {
  var r = /.+\.(.+)$/.exec(filename);
  return r ? r[1] : null;
}

Antwoord 28

Het antwoord van Wallacer is aardig, maar er is nog een controle nodig.

Als het bestand geen extensie heeft, zal het bestandsnaam als extensie gebruiken, wat niet goed is.

Probeer deze:

return ( filename.indexOf('.') > 0 ) ? filename.split('.').pop().toLowerCase() : 'undefined';

Antwoord 29

Vergeet niet dat sommige bestanden geen extensie kunnen hebben, dus:

var parts = filename.split('.');
return (parts.length > 1) ? parts.pop() : '';

Antwoord 30

var file = "hello.txt";
var ext = (function(file, lio) { 
  return lio === -1 ? undefined : file.substring(lio+1); 
})(file, file.lastIndexOf("."));
// hello.txt -> txt
// hello.dolly.txt -> txt
// hello -> undefined
// .hello -> hello

Other episodes