Javascript: cómo extraer el nombre de archivo de un control de entrada de archivo

117

Cuando un usuario selecciona un archivo en una página web, quiero poder extraer solo el nombre del archivo.

Probé la función str.search pero parece fallar cuando el nombre del archivo es algo como esto: c: \ uploads \ ilike.this.file.jpg .

¿Cómo podemos extraer solo el nombre del archivo sin extensión?

Yogi Yang 007
fuente

Respuestas:

127

Suponiendo que su <input type = "file"> tiene una identificación de carga, esto debería funcionar:

var fullPath = document.getElementById('upload').value;
if (fullPath) {
    var startIndex = (fullPath.indexOf('\\') >= 0 ? fullPath.lastIndexOf('\\') : fullPath.lastIndexOf('/'));
    var filename = fullPath.substring(startIndex);
    if (filename.indexOf('\\') === 0 || filename.indexOf('/') === 0) {
        filename = filename.substring(1);
    }
    alert(filename);
}
Ian Oxley
fuente
Gracias, esto parece funcionar bien, pero solo quiero un nombre de archivo sin extensión. ¿Cómo puedo hacer eso en el código anterior?
Yogi Yang 007
Agregué estas dos líneas de código para extraer solo el nombre del archivo sin extensión: "nombre de archivo = nombre de archivo.substring (0, nombre de archivo.length-4); nombre de archivo = nombre de archivo.toLowerCase ();"
Yogi Yang 007
13
No, no quieres hacerlo de esa manera, dice Yogi Yang. En su lugar, use: filename = filename.substring(0, filename.lastIndexOf('.'));Porque su camino fallará con extensiones de más de 3 caracteres, por lo tanto: .html, .jpeg, etc.
Yeti
1
¿Cómo obtener los nombres de archivo en caso de selección de archivos múltiples?
avngr
¿Por qué no calcular startIndex así? var startIndex = Math.max(fullPath.lastIndexOf('\\'), fullPath.lastIndexOf('/')) + 1;
nollidge
196

Para dividir la cadena ({filepath} / {filename}) y obtener el nombre del archivo, puede usar algo como esto:

str.split(/(\\|\/)/g).pop()

"El método pop elimina el último elemento de una matriz y devuelve ese valor a la persona que llama".
Red de desarrolladores de Mozilla

Ejemplo:

de: "/home/user/file.txt".split(/(\\|\/)/g).pop()

usted obtiene: "file.txt"

VallaPeligro
fuente
5
También puede hacer eso solo con expresiones regulares y sin ninguna operación de matriz:var filename = filepath.replace(/^.*?([^\\\/]*)$/, '$1');
vog
1
La respuesta de vog está muy cerca de la respuesta 100% precisa a la pregunta (excepto que necesita quitar la extensión). Un nombre de archivo no es diferente de cualquier otra cadena.
Jon Watte
1
La expresión regular dividida se puede acortar a [\\/]. Además, también se pidió eliminar la extensión del archivo. Para obtener una solución completa, consulte: stackoverflow.com/a/32156800/19163
vog
multiplataforma, concisa. Excelente.
Marc
Gran solución, no entiendo cómo funciona y por eso me gusta más!
Chatoxz
92

Hoy en día existe una forma mucho más sencilla:

var fileInput = document.getElementById('upload');   
var filename = fileInput.files[0].name;
maxime schoeni
fuente
5
Cheque fileInput.files.length antes de llamar .name, en caso de que el usuario haya hecho clic en cancelar.
marcovtwout
29

Muy simple

let file = $("#fileupload")[0].files[0]; 
file.name
Uchenna
fuente
En caso de que esté usando TypeScript, entonces su $ ("# fileupload") [0] ["files"] [0];
Morvael
18

Asumiendo:

<input type="file" name="file1" id="theFile">

El JavaScript sería:

var fileName = document.getElementById('theFile').files[0].name;
Xedret
fuente
8
var pieces = str.split('\\');
var filename = pieces[pieces.length-1];
TM.
fuente
Esto supone que el usuario está ejecutando Windows. Otros sistemas operativos utilizan diferentes separadores de ruta de archivo.
Quentin
¿Necesitaría comprobar el carácter '/' también para usuarios que no son de Windows, por ejemplo, if (! Pieces) {str.split ('/'); }? Agradable solución simple aunque +1
Ian Oxley
IIRC, IE es el único navegador que proporciona la ruta completa del archivo de todos modos ... No necesitará dividir en otros navegadores como Firefox, por lo que aún funciona. Aunque admito que no he probado TODOS los navegadores linux / unix.
TM.
6
str.split (/ (\\ | \ /) / g); para windows y * nix
Tracker1
@TM. Chrome usa una variable de ruta falsa por seguridad que es fea; iirc es diferente según el sistema operativo en el que se encuentre.
lededje
5

Supongo que desea eliminar todas las extensiones, es decir, /tmp/test/somefile.tar.gza somefile.

Enfoque directo con expresiones regulares:

var filename = filepath.match(/^.*?([^\\/.]*)[^\\/]*$/)[1];

Enfoque alternativo con operación de expresiones regulares y matrices:

var filename = filepath.split(/[\\/]/g).pop().split('.')[0];
vog
fuente
1
Esto no quita la extensión, como se solicitó.
Jon Watte
Fijo. ¡Gracias por la pista!
vog
4

Acabo de hacer mi propia versión de esto. Mi función se puede usar para extraer lo que quieras de ella, si no la necesitas todo, puedes eliminar fácilmente algún código.

<html>
<body>
<script type="text/javascript">
// Useful function to separate path name and extension from full path string
function pathToFile(str)
{
    var nOffset = Math.max(0, Math.max(str.lastIndexOf('\\'), str.lastIndexOf('/')));
    var eOffset = str.lastIndexOf('.');
    if(eOffset < 0 && eOffset < nOffset)
    {
        eOffset = str.length;
    }
    return {isDirectory: eOffset === str.length, // Optionally: && nOffset+1 === str.length if trailing slash means dir, and otherwise always file
            path: str.substring(0, nOffset),
            name: str.substring(nOffset > 0 ? nOffset + 1 : nOffset, eOffset),
            extension: str.substring(eOffset > 0 ? eOffset + 1 : eOffset, str.length)};
}

// Testing the function
var testcases = [
    "C:\\blabla\\blaeobuaeu\\testcase1.jpeg",
    "/tmp/blabla/testcase2.png",
    "testcase3.htm",
    "C:\\Testcase4", "/dir.with.dots/fileWithoutDots",
    "/dir.with.dots/another.dir/"
];
for(var i=0;i<testcases.length;i++)
{
    var file = pathToFile(testcases[i]);
    document.write("- " + (file.isDirectory ? "Directory" : "File") + " with name '" + file.name + "' has extension: '" + file.extension + "' is in directory: '" + file.path + "'<br />");
}
</script>
</body>
</html>

Producirá lo siguiente:

  • El archivo con el nombre 'testcase1' tiene la extensión: 'jpeg' está en el directorio: 'C: \ blabla \ blaeobuaeu'
  • El archivo con el nombre 'testcase2' tiene la extensión: 'png' está en el directorio: '/ tmp / blabla'
  • El archivo con el nombre 'testcase3' tiene la extensión: 'htm' está en el directorio: ''
  • El directorio con el nombre 'Testcase4' tiene la extensión: '' está en el directorio: 'C:'
  • El directorio con el nombre 'fileWithoutDots' tiene la extensión: '' está en el directorio: '/dir.with.dots'
  • El directorio con el nombre '' tiene extensión: '' está en el directorio: '/dir.with.dots/another.dir'

Con && nOffset+1 === str.lengthagregado a isDirectory:

  • El archivo con el nombre 'testcase1' tiene la extensión: 'jpeg' está en el directorio: 'C: \ blabla \ blaeobuaeu'
  • El archivo con el nombre 'testcase2' tiene la extensión: 'png' está en el directorio: '/ tmp / blabla'
  • El archivo con el nombre 'testcase3' tiene la extensión: 'htm' está en el directorio: ''
  • El directorio con el nombre 'Testcase4' tiene la extensión: '' está en el directorio: 'C:'
  • El directorio con el nombre 'fileWithoutDots' tiene la extensión: '' está en el directorio: '/dir.with.dots'
  • El directorio con el nombre '' tiene extensión: '' está en el directorio: '/dir.with.dots/another.dir'

Dados los casos de prueba, puede ver que esta función funciona de manera bastante robusta en comparación con los otros métodos propuestos aquí.

Nota para los novatos sobre \\: \ es un carácter de escape, por ejemplo, \ n significa una nueva línea y una pestaña \ ta. Para que sea posible escribir \ n, debe escribir \\ n.

Yeti
fuente
1
Tenga cuidado con esta ruta: dir.with.dots / fileWithoutDots ya que obtendrá eOffset menos que nOffset y confundirá las expresiones de extracción.
Jesse Chisholm
Sí, lo arreglé. Ahora eso también debería funcionar correctamente (agregado && eOffset < nOffset).
Yeti
2

Entrada : C:\path\Filename.ext
Salida :Filename

En código HTML, establezca el onChangevalor de Archivo así ...

<input type="file" name="formdata" id="formdata" onchange="setfilename(this.value)"/>

Suponiendo que su ID de campo de texto es 'wpName' ...

<input type="text" name="wpName" id="wpName">

JavaScript

<script>
  function setfilename(val)
  {
    filename = val.split('\\').pop().split('/').pop();
    filename = filename.substring(0, filename.lastIndexOf('.'));
    document.getElementById('wpName').value = filename;
  }
</script>
DxTx
fuente
1

Ninguna de las respuestas altamente votadas proporciona "solo el nombre del archivo sin extensión" y las otras soluciones son demasiado código para un trabajo tan simple.

Creo que esto debería ser un ejemplo para cualquier programador de JavaScript. Es una expresión regular muy simple:

function basename(prevname) {
    return prevname.replace(/^(.*[/\\])?/, '').replace(/(\.[^.]*)$/, '');
}

Primero, elimine cualquier cosa hasta la última barra, si está presente.

Luego, quite cualquier cosa después del último período, si está presente.

Es simple, es robusto, implementa exactamente lo que se pide. ¿Me estoy perdiendo de algo?

Jon Watte
fuente
1
"una expresión regular muy simple" ... Bueno, en realidad estas son dos expresiones regulares. :-) Vea mi respuesta para una solución de expresión regular única.
vog
Sí, también hay una reescritura obvia para empaquetar esas dos expresiones regulares en una sola expresión regular usando el operador de tubería (|). Creo que el código tal como está escrito es más claro, pero se ejecuta a través de la cadena dos veces, lo que sería un problema si la cadena es generalmente bastante larga. (Las rutas de archivo normalmente no lo son, pero pueden serlo).
Jon Watte
1
Solo estaba quisquilloso. Por favor, no te lo tomes en serio. No es necesario optimizar, todas las soluciones propuestas son lo suficientemente rápidas. Las rutas de archivo muy largas siguen siendo kilobytes, no gigabytes. Y esta función se activará una vez por cada carga de archivo, no 1000 veces en un lote. Lo único que importa aquí es la exactitud y claridad del código.
vog
1
// HTML
<input type="file" onchange="getFileName(this)">

// JS
function getFileName(input) {
    console.log(input.files[0].name) // With extension
    console.log(input.files[0].name.replace(/\.[^/.]+$/, '')) // Without extension
}

Cómo quitar la extensión

Mikel
fuente
1
Esto pasa por alto una parte importante de la pregunta, "extraer solo el nombre del archivo sin extensión". Es útil leer la pregunta con atención antes de saltar a responderla.
zeh
1
var path = document.getElementById('upload').value;//take path
var tokens= path.split('\\');//split path
var filename = tokens[tokens.length-1];//take file name
Luca C.
fuente
0

Ninguna de las respuestas anteriores funcionó para mí, aquí está mi solución que actualiza una entrada deshabilitada con el nombre de archivo:

<script type="text/javascript"> 
  document.getElementById('img_name').onchange = function () {
  var filePath = this.value;
    if (filePath) {
      var fileName = filePath.replace(/^.*?([^\\\/]*)$/, '$1');
      document.getElementById('img_name_input').value = fileName;
    }
  };
</script>
sigi
fuente
-2

Si está utilizando jQuery entonces

$("#fileupload").val();
Rajat Bansal
fuente
val () en realidad devolvería la ruta completa del archivo, que es lo que no quiere.
FabricioG