Javascript - como extrair o nome do arquivo de um controle de entrada de arquivo


117

Quando um usuário seleciona um arquivo em uma página da web, desejo extrair apenas o nome do arquivo.

Eu tentei a função str.search, mas parece falhar quando o nome do arquivo é algo assim: c: \ uploads \ ilike.this.file.jpg .

Como podemos extrair apenas o nome do arquivo sem extensão?

Respostas:


127

Supondo que seu <input type = "file"> tenha uma id de upload, isso deve resolver o problema:

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

Obrigado, isso parece funcionar bem, mas eu só quero o nome do arquivo sem extensão. Como posso fazer isso no código acima.
Yogi Yang 007

Eu adicionei essas duas linhas de código para extrair apenas o nome do arquivo sem extensão: "filename = filename.substring (0, filename.length-4); filename = filename.toLowerCase ();"
Yogi Yang 007

13
Não, você não quer fazer assim que diz o Yogi Yang. Em vez disso, use: filename = filename.substring(0, filename.lastIndexOf('.'));Porque seu caminho falhará com extensões de mais caracteres do que 3, assim: .html, .jpeg etc.
Yeti

1
como obter os nomes dos arquivos em caso de seleção de vários arquivos?
avngr

Por que não apenas calcular startIndex assim? var startIndex = Math.max(fullPath.lastIndexOf('\\'), fullPath.lastIndexOf('/')) + 1;
nollidge

196

Para dividir a string ({filepath} / {filename}) e obter o nome do arquivo, você pode usar algo assim:

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

"O método pop remove o último elemento de uma matriz e retorna esse valor para o chamador."
Mozilla Developer Network

Exemplo:

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

você obtém: "file.txt"


5
Você também pode fazer isso apenas com regexes e sem qualquer operação de matriz:var filename = filepath.replace(/^.*?([^\\\/]*)$/, '$1');
vog

1
A resposta de vog está realmente próxima da resposta 100% precisa à pergunta (exceto pela necessidade de remover a extensão). Um nome de arquivo não é diferente de qualquer outra string.
Jon Watte

1
O regex dividido pode ser reduzido para [\\/]. Além disso, foi solicitada a remoção da extensão do arquivo também. Para obter uma solução completa, consulte: stackoverflow.com/a/32156800/19163
vog

multiplataforma, conciso. Ótimo.
Marc

Ótima solução, não entendo como funciona e é por isso que gosto mais!
Chatoxz

92

Hoje em dia existe uma maneira muito mais simples:

var fileInput = document.getElementById('upload');   
var filename = fileInput.files[0].name;

5
Verifique fileInput.files.lengthantes de ligar .name, caso o usuário tenha clicado em cancelar.
marcovtwout

29

Muito simples

let file = $("#fileupload")[0].files[0]; 
file.name

Caso você esteja usando o TypeScript, então é $ ("# fileupload") [0] ["files"] [0];
Morvael

18

Supondo:

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

O JavaScript seria:

var fileName = document.getElementById('theFile').files[0].name;

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

Isso pressupõe que o usuário está executando o Windows. Outros sistemas operacionais usam diferentes separadores de caminho de arquivo.
Quentin

Você precisaria verificar o caractere '/' também para usuários não-Windows, por exemplo, if (! Pieces) {str.split ('/'); }? Boa solução simples, embora +1
Ian Oxley

IIRC, IE é o único navegador que fornece o caminho completo do arquivo de qualquer maneira ... Você não precisará dividir em outros navegadores como o Firefox, por isso ainda funciona. Embora eu admita que não experimentei TODOS os navegadores linux / unix.
TM.

6
str.split (/ (\\ | \ /) / g); para windows e * nix
Tracker1

@TM. O Chrome usa uma variável de caminho falso para segurança, o que é feio; iirc é diferente dependendo do sistema operacional em que você está.
lededje

5

Presumo que você deseja remover todas as extensões, ou seja, /tmp/test/somefile.tar.gzpara somefile.

Abordagem direta com regex:

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

Abordagem alternativa com regex e operação de array:

var filename = filepath.split(/[\\/]/g).pop().split('.')[0];

1
Isso não remove a extensão, conforme solicitado.
Jon Watte

Fixo. Obrigado pela dica!
vog

4

Acabei de fazer minha própria versão disso. Minha função pode ser usada para extrair o que você quiser dela, se você não precisar de tudo, então você pode remover facilmente algum 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>

Irá produzir o seguinte:

  • O arquivo com o nome 'testcase1' tem extensão: 'jpeg' está no diretório: 'C: \ blabla \ blaeobuaeu'
  • O arquivo com o nome 'testcase2' tem extensão: 'png' está no diretório: '/ tmp / blabla'
  • O arquivo com o nome 'testcase3' tem extensão: 'htm' está no diretório: ''
  • O diretório com o nome 'Testcase4' tem extensão: '' está no diretório: 'C:'
  • O diretório com o nome 'fileWithoutDots' tem extensão: '' está no diretório: '/dir.with.dots'
  • O diretório com o nome '' tem extensão: '' está no diretório: '/dir.with.dots/another.dir'

Com && nOffset+1 === str.lengthadicionado a isDirectory:

  • O arquivo com o nome 'testcase1' tem extensão: 'jpeg' está no diretório: 'C: \ blabla \ blaeobuaeu'
  • O arquivo com o nome 'testcase2' tem extensão: 'png' está no diretório: '/ tmp / blabla'
  • O arquivo com o nome 'testcase3' tem extensão: 'htm' está no diretório: ''
  • O diretório com o nome 'Testcase4' tem extensão: '' está no diretório: 'C:'
  • O diretório com o nome 'fileWithoutDots' tem extensão: '' está no diretório: '/dir.with.dots'
  • O diretório com o nome '' tem extensão: '' está no diretório: '/dir.with.dots/another.dir'

Dados os casos de teste, você pode ver que essa função funciona de maneira bastante robusta em comparação com os outros métodos propostos aqui.

Nota para iniciantes sobre o \\: \ é um caractere de escape, por exemplo \ n significa uma nova linha e \ ta tab. Para tornar possível escrever \ n, você deve realmente digitar \\ n.


1
Cuidado com este caminho: dir.with.dots / fileWithoutDots, pois você obterá eOffset menor que nOffset e confundirá as expressões de extração.
Jesse Chisholm

Sim, consertei. Agora, isso também deve funcionar corretamente (adicionado && eOffset < nOffset).
Yeti

2

Entrada : C:\path\Filename.ext
Saída :Filename

No código HTML, defina o onChangevalor do arquivo como este ...

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

Supondo que seu id de campo de texto seja '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

Nenhuma das respostas altamente votadas realmente fornecem "apenas o nome do arquivo sem extensão" e as outras soluções são código demais para um trabalho tão simples.

Eu acho que isso deve ser uma linha para qualquer programador de JavaScript. É uma expressão regular muito simples:

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

Primeiro, retire tudo até a última barra, se houver.

Em seguida, retire qualquer coisa após a última menstruação, se houver.

É simples, é robusto, implementa exatamente o que é pedido. Estou esquecendo de algo?


1
"uma expressão regular muito simples" ... Bem, na verdade, essas são duas expressões regulares. :-) Veja minha resposta para uma solução de regex único.
vog

Sim, há também uma reescrita óbvia para compactar essas duas regexes em uma única regex usando o operador pipe (|). Acho que o código escrito é mais claro, mas ele passa pela string duas vezes, o que seria um problema se a string geralmente fosse muito longa. (Os caminhos de arquivo normalmente não são, mas podem ser.)
Jon Watte

1
Eu estava apenas criticando. Por favor, não leve isso a sério. Não há necessidade de otimizar, todas as soluções propostas são mais do que rápidas. Caminhos de arquivo muito longos ainda são kilobytes, não gigabytes. E esta função será acionada uma vez por upload de arquivo, não 1000x em um lote. As únicas coisas que importam aqui são a exatidão e a clareza do 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
}

Como remover a extensão


1
Isso perde uma parte importante da questão, "extraia apenas o nome do arquivo sem extensão". Isso ajuda a ler a pergunta cuidadosamente antes de pular para respondê-la.
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

Nenhuma das respostas acima funcionou para mim, aqui está minha solução que atualiza uma entrada desativada com o nome do arquivo:

<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

Se você estiver usando jQuery, então

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

val () retornaria, na verdade, todo o caminho do arquivo, o que ele não deseja.
FabricioG
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.