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?

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

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"


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;

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

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;

8
var pieces = str.split('\\');
var filename = pieces[pieces.length-1];

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];

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.


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>

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?


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


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

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>

-2

Si está utilizando jQuery entonces

$("#fileupload").val();

val () en realidad devolvería la ruta completa del archivo, que es lo que no quiere.
FabricioG
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.