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?

Yogi Yang 007
fonte

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);
}
Ian Oxley
fonte
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"

VallaDanger
fonte
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;
maxime schoeni
fonte
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
Uchenna
fonte
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;
Xedret
fonte
8
var pieces = str.split('\\');
var filename = pieces[pieces.length-1];
TM.
fonte
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];
vog
fonte
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.

Yeti
fonte
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>
DxTx
fonte
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?

Jon Watte
fonte
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

Mikel
fonte
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
Luca C.
fonte
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>
sigi
fonte
-2

Se você estiver usando jQuery, então

$("#fileupload").val();
Rajat Bansal
fonte
val () retornaria, na verdade, todo o caminho do arquivo, o que ele não deseja.
FabricioG