Javascript - Как извлечь имя файла из элемента управления вводом файла

118

Когда пользователь выбирает файл на веб-странице, я хочу иметь возможность извлечь только имя файла.

Я пробовал использовать функцию str.search, но, похоже, она не работает, когда имя файла выглядит примерно так: c: \ uploads \ ilike.this.file.jpg .

Как мы можем извлечь только имя файла без расширения?

Йоги Ян 007
источник

Ответы:

128

Предполагая, что ваш <input type = "file"> имеет идентификатор загрузки, это должно помочь:

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);
}
Ян Оксли
источник
Спасибо, похоже, работает хорошо, но мне просто нужно имя файла без расширения. Как я могу это сделать в приведенном выше коде.
Йоги Ян 007,
Я добавил эти две строки кода, чтобы извлечь только имя файла без расширения: "filename = filename.substring (0, filename.length-4); filename = filename.toLowerCase ();"
Йоги Ян 007,
13
Нет, ты не хочешь делать это так, как говорит Йоги Ян. Вместо этого используйте: filename = filename.substring(0, filename.lastIndexOf('.'));Потому что его способ потерпит неудачу с расширениями, состоящими из более чем 3 символов, например: .html, .jpeg и т. Д.
Йети
1
как получить имена файлов в случае выбора нескольких файлов?
avngr
Почему бы просто не рассчитать startIndex вот так? var startIndex = Math.max(fullPath.lastIndexOf('\\'), fullPath.lastIndexOf('/')) + 1;
nollidge
197

Чтобы разделить строку ({filepath} / {filename}) и получить имя файла, вы можете использовать что-то вроде этого:

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

«Метод pop удаляет последний элемент из массива и возвращает это значение вызывающей стороне».
Сеть разработчиков Mozilla

Пример:

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

ты получаешь: "file.txt"

VallaDanger
источник
5
Вы также можете сделать это с помощью регулярных выражений и без каких-либо операций с массивом:var filename = filepath.replace(/^.*?([^\\\/]*)$/, '$1');
vog
1
Ответ vog действительно близок к 100% точному ответу на вопрос (за исключением необходимости убрать расширение). Имя файла не отличается от любой другой строки.
Джон Уотт,
1
Разделенное регулярное выражение можно сократить до [\\/]. Более того, попросили убрать и расширение файла. Для полного решения см .: stackoverflow.com/a/32156800/19163
vog
мультиплатформенность, лаконичность. Отлично.
Марк
Отличное решение, не понимаю, как оно работает, а потому нравится больше!
Chatoxz
92

В настоящее время существует более простой способ:

var fileInput = document.getElementById('upload');   
var filename = fileInput.files[0].name;
Максим Шёни
источник
5
Проверьте fileInput.files.lengthперед звонком .name, если пользователь нажал кнопку «Отмена».
marcovtwout
29

Очень просто

let file = $("#fileupload")[0].files[0]; 
file.name
Uchenna
источник
Если вы используете TypeScript, то его $ ("# fileupload") [0] ["files"] [0];
Morvael
19

Предполагая, что:

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

Код JavaScript будет:

var fileName = document.getElementById('theFile').files[0].name;
Xedret
источник
8
var pieces = str.split('\\');
var filename = pieces[pieces.length-1];
TM.
источник
Это предполагает, что пользователь работает под управлением Windows. В других операционных системах используются другие разделители путей к файлам.
Квентин
Нужно ли вам проверять наличие символа «/» также для пользователей, отличных от Windows, например, if (!ieces) {str.split ('/'); }? Хорошее простое решение +1
Ян Оксли
IIRC, IE - единственный браузер, который в любом случае дает полный путь к файлу ... Вам не нужно разделять файлы в других браузерах, таких как Firefox, поэтому он по-прежнему работает. Хотя, признаюсь, я не пробовал КАЖДЫЙ браузер linux / unix.
ТМ.
6
str.split (/ (\\ | \ /) / г); для windows и * nix
Tracker1
@TM. Chrome использует фиктивную переменную пути для безопасности, что некрасиво; iirc зависит от того, на какой ОС вы работаете.
lededje 07
5

Я предполагаю , что вы хотите , чтобы лишить все расширения, то есть /tmp/test/somefile.tar.gzв somefile.

Прямой подход с регулярным выражением:

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

Альтернативный подход с регулярным выражением и операцией с массивом:

var filename = filepath.split(/[\\/]/g).pop().split('.')[0];
ВОГ
источник
1
Это не лишает расширение, как просили.
Джон Уотт,
Исправлена. Спасибо за подсказку!
vog
4

Я только что сделал свою версию этого. Моя функция может быть использована для извлечения из нее всего, что вы хотите, если вам не нужно все это, вы можете легко удалить некоторый код.

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

Будет выведено следующее:

  • Файл с именем 'testcase1' имеет расширение: 'jpeg' находится в каталоге: 'C: \ blabla \ blaeobuaeu'
  • Файл с именем 'testcase2' имеет расширение: 'png' находится в каталоге: '/ tmp / blabla'
  • Файл с именем 'testcase3' имеет расширение: 'htm' находится в каталоге: ''
  • Каталог с именем Testcase4 имеет расширение: '' находится в каталоге: 'C:'
  • Каталог с именем 'fileWithoutDots' имеет расширение: '' находится в каталоге: '/dir.with.dots'
  • Каталог с именем '' имеет расширение: '' находится в каталоге: '/dir.with.dots/another.dir'

С && nOffset+1 === str.lengthдобавлением isDirectory:

  • Файл с именем 'testcase1' имеет расширение: 'jpeg' находится в каталоге: 'C: \ blabla \ blaeobuaeu'
  • Файл с именем 'testcase2' имеет расширение: 'png' находится в каталоге: '/ tmp / blabla'
  • Файл с именем 'testcase3' имеет расширение: 'htm' находится в каталоге: ''
  • Каталог с именем Testcase4 имеет расширение: '' находится в каталоге: 'C:'
  • Каталог с именем 'fileWithoutDots' имеет расширение: '' находится в каталоге: '/dir.with.dots'
  • Каталог с именем '' имеет расширение: '' находится в каталоге: '/dir.with.dots/another.dir'

Учитывая тестовые примеры, вы можете видеть, что эта функция работает довольно надежно по сравнению с другими предлагаемыми здесь методами.

Примечание для новичков о том, что \\: \ - это escape-символ, например, \ n означает новую строку и вкладку \ ta. Чтобы можно было писать \ n, вы должны набрать \\ n.

Йети
источник
1
Следите за этим путем: dir.with.dots / fileWithoutDots, так как вы получите eOffset меньше nOffset и запутаете выражения извлечения.
Джесси Чисхолм
Да, исправил. Теперь это тоже должно работать правильно (добавлено && eOffset < nOffset).
Yeti
2

Вход : C:\path\Filename.ext
Выход :Filename

В HTML-коде установите onChangeзначение File следующим образом ...

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

Предполагая, что ваш идентификатор текстового поля - 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
источник
1

Ни один из получивших высокую оценку ответов на самом деле не предоставляет «только имя файла без расширения», а другие решения представляют собой слишком много кода для такой простой работы.

Я думаю, что это должно быть однострочным для любого программиста JavaScript. Это очень простое регулярное выражение:

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

Сначала удалите все до последней косой черты, если она есть.

Затем снимите все, что было после последней менструации, если таковое имеется.

Он прост, он надежен, он выполняет именно то, что требуется. Я что-то упускаю?

Джон Ватт
источник
1
"очень простое регулярное выражение" ... Ну, на самом деле это два регулярных выражения. :-) См. Мой ответ для решения с одним регулярным выражением.
vog
Да, существует также очевидная перезапись, чтобы упаковать эти два регулярных выражения в одно регулярное выражение с помощью оператора вертикальной черты (|). Я думаю, что написанный код более понятен, но он дважды проходит через строку, что было бы проблемой, если строка обычно довольно длинная. (Пути к файлам обычно не используются, но могут быть.)
Джон Уотт,
1
Я просто придирался. Пожалуйста, не относись к этому серьезно. Оптимизировать не нужно, все предлагаемые решения более чем достаточно быстрые. Очень длинные пути к файлам по-прежнему составляют килобайты, а не гигабайты. И эта функция будет запускаться один раз при загрузке файла, а не 1000 раз за один раз. Единственное, что здесь имеет значение, - это правильность и ясность кода.
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
}

Как удалить расширение

Mikel
источник
1
При этом упускается важная часть вопроса: «извлечь только имя файла без расширения». Это помогает сначала внимательно прочитать вопрос, прежде чем приступать к ответу на него.
zeh 07
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

Ни один из приведенных выше ответов не помог мне, вот мое решение, которое обновляет отключенный ввод с именем файла:

<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

Если вы используете jQuery, тогда

$("#fileupload").val();
Раджат Бансал
источник
val () фактически вернет весь путь к файлу, чего он не хочет.
FabricioG,