Javascript - Cách trích xuất tên tệp từ điều khiển đầu vào tệp


117

Khi người dùng chọn một tệp trong trang web, tôi muốn chỉ có thể trích xuất tên tệp.

Tôi đã thử hàm str.search nhưng có vẻ như không thành công khi tên tệp giống như thế này: c: \ uploads \ ilike.this.file.jpg .

Làm thế nào chúng tôi có thể giải nén chỉ tên tệp mà không có phần mở rộng?

Câu trả lời:


127

Giả sử <input type = "file"> của bạn có id tải lên, điều này hy vọng sẽ thực hiện được mẹo:

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

Cảm ơn, điều này có vẻ hoạt động tốt, nhưng tôi chỉ muốn tên tệp không có phần mở rộng. Làm thế nào tôi có thể làm điều đó trong đoạn mã trên.
Yogi Yang 007

Tôi đã thêm hai dòng mã này để chỉ trích xuất tên tệp mà không có phần mở rộng: "filename = filename.substring (0, filename.length-4); filename = filename.toLowerCase ();"
Yogi Yang 007

13
Không, bạn không muốn làm theo cách Yogi Yang nói. Thay vào đó, hãy sử dụng: filename = filename.substring(0, filename.lastIndexOf('.'));Bởi vì cách của anh ấy sẽ không thành công với phần mở rộng có nhiều ký tự hơn 3, do đó: .html, .jpeg, v.v.
Yeti

1
Làm thế nào để lấy tên tệp trong trường hợp chọn nhiều tệp?
trung bình

Tại sao không chỉ tính toán startIndex như vậy? var startIndex = Math.max(fullPath.lastIndexOf('\\'), fullPath.lastIndexOf('/')) + 1;
nollidge

196

Để tách chuỗi ({filepath} / {filename}) và lấy tên tệp, bạn có thể sử dụng một cái gì đó như sau:

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

"Phương thức pop xóa phần tử cuối cùng khỏi một mảng và trả về giá trị đó cho trình gọi."
Mạng nhà phát triển Mozilla

Thí dụ:

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

bạn lấy: "file.txt"


5
Bạn cũng có thể làm điều đó chỉ với regexes và không cần bất kỳ thao tác mảng nào:var filename = filepath.replace(/^.*?([^\\\/]*)$/, '$1');
vog 22/08/15

1
Câu trả lời của vog thực sự gần với câu trả lời chính xác 100% cho câu hỏi (ngoại trừ cần phải loại bỏ phần mở rộng.) Tên tệp không khác bất kỳ chuỗi nào khác.
Jon Watte

1
Regex phân tách có thể được rút ngắn thành [\\/]. Hơn nữa, nó cũng được yêu cầu loại bỏ phần mở rộng tệp. Để có giải pháp hoàn chỉnh, hãy xem: stackoverflow.com/a/32156800/19163
vog

đa dạng, ngắn gọn. Tuyệt quá.
Marc

Giải pháp tuyệt vời, tôi không hiểu nó hoạt động như thế nào và đó là lý do tại sao thích nó hơn!
Chatoxz

92

Ngày nay có một cách đơn giản hơn nhiều:

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

5
Kiểm tra fileInput.files.lengthtrước khi gọi .name, phòng trường hợp người dùng bấm hủy.
marcovtwout

29

Rất đơn giản

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

Trong trường hợp bạn đang sử dụng TypeScript thì $ ("# fileupload") [0] ["files"] [0];
Morvael

18

Giả định:

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

JavaScript sẽ là:

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

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

Điều này giả định rằng người dùng đang chạy Windows. Các hệ điều hành khác sử dụng các trình phân tách đường dẫn tệp khác nhau.
Quentin

Bạn có cần kiểm tra ký tự '/' cũng như đối với người dùng không phải Windows, ví dụ if (! Piece) {str.split ('/'); }? Giải pháp đơn giản tuyệt vời mặc dù +1
Ian Oxley

IIRC, IE là trình duyệt duy nhất cung cấp đường dẫn đầy đủ của tệp tin ... Bạn sẽ không cần phải chia nhỏ trên các trình duyệt khác như Firefox, vì vậy nó vẫn hoạt động. Mặc dù tôi thừa nhận rằng tôi chưa thử MỌI trình duyệt linux / unix.
TM.

6
str.split (/ (\\ | \ /) / g); cho windows và * nix
Tracker1

@TM. Chrome sử dụng một biến đường dẫn giả để đảm bảo an toàn, điều này rất xấu; iirc nó khác nhau tùy thuộc vào hệ điều hành bạn đang sử dụng.
lededje

5

Tôi giả sử bạn muốn loại bỏ tất cả các phần mở rộng, tức là /tmp/test/somefile.tar.gzđến somefile.

Cách tiếp cận trực tiếp với regex:

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

Cách tiếp cận thay thế với hoạt động regex và mảng:

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

1
Điều này không loại bỏ phần mở rộng, như đã yêu cầu.
Jon Watte

Đã sửa. Cảm ơn vì gợi ý!
vog

4

Tôi chỉ tạo phiên bản của riêng tôi về điều này. Hàm của tôi có thể được sử dụng để trích xuất bất cứ thứ gì bạn muốn từ nó, nếu bạn không cần tất cả, thì bạn có thể dễ dàng xóa một số mã.

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

Sẽ xuất như sau:

  • Tệp có tên 'testcase1' có phần mở rộng: 'jpeg' nằm trong thư mục: 'C: \ blabla \ blaeobuaeu'
  • Tệp có tên 'testcase2' có phần mở rộng: 'png' nằm trong thư mục: '/ tmp / blabla'
  • Tệp có tên 'testcase3' có phần mở rộng: 'htm' nằm trong thư mục: ''
  • Thư mục có tên 'Testcase4' có phần mở rộng: '' nằm trong thư mục: 'C:'
  • Thư mục có tên 'fileWithoutDots' có phần mở rộng: '' nằm trong thư mục: '/dir.with.dots'
  • Thư mục có tên '' có phần mở rộng: '' nằm trong thư mục: '/dir.with.dots/aosystem.dir'

Với && nOffset+1 === str.lengthđược thêm vào isDirectory:

  • Tệp có tên 'testcase1' có phần mở rộng: 'jpeg' nằm trong thư mục: 'C: \ blabla \ blaeobuaeu'
  • Tệp có tên 'testcase2' có phần mở rộng: 'png' nằm trong thư mục: '/ tmp / blabla'
  • Tệp có tên 'testcase3' có phần mở rộng: 'htm' nằm trong thư mục: ''
  • Thư mục có tên 'Testcase4' có phần mở rộng: '' nằm trong thư mục: 'C:'
  • Thư mục có tên 'fileWithoutDots' có phần mở rộng: '' nằm trong thư mục: '/dir.with.dots'
  • Thư mục có tên '' có phần mở rộng: '' nằm trong thư mục: '/dir.with.dots/aosystem.dir'

Với các tủ thử, bạn có thể thấy chức năng này hoạt động khá mạnh mẽ so với các phương pháp được đề xuất khác ở đây.

Lưu ý cho người mới về \\: \ là một ký tự thoát, ví dụ \ n có nghĩa là một dòng mới và tab \ ta. Để có thể viết \ n, bạn phải thực sự nhập \\ n.


1
Hãy để ý đường dẫn này: dir.with.dots / fileWithoutDots vì bạn sẽ nhận được eOffset ít hơn nOffset và làm nhầm lẫn các biểu thức trích xuất.
Jesse Chisholm

Vâng, đã sửa nó. Bây giờ nó cũng sẽ hoạt động bình thường (thêm vào && eOffset < nOffset).
Yeti

2

Đầu vào : C:\path\Filename.ext
Đầu ra :Filename

Trong mã HTML, hãy đặt onChangegiá trị Tệp như thế này ...

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

Giả sử id trường văn bản của bạn là '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

Không có câu trả lời nào trong số các câu trả lời được ủng hộ cao thực sự cung cấp "chỉ tên tệp mà không có phần mở rộng" và các giải pháp khác là quá nhiều mã cho một công việc đơn giản như vậy.

Tôi nghĩ rằng đây nên là một phần mềm cho bất kỳ lập trình viên JavaScript nào. Đó là một biểu thức chính quy rất đơn giản:

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

Đầu tiên, tước bất cứ thứ gì cho đến dấu gạch chéo cuối cùng, nếu có.

Sau đó, loại bỏ bất cứ thứ gì sau kỳ kinh cuối cùng, nếu có.

Nó đơn giản, nó mạnh mẽ, nó thực hiện chính xác những gì được yêu cầu. Tui bỏ lỡ điều gì vậy?


1
"một biểu thức chính quy rất đơn giản" ... Thực ra đây là hai biểu thức regex. :-) Xem câu trả lời của tôi cho một giải pháp regex duy nhất.
vog

Có, cũng có một cách viết lại rõ ràng để đóng gói hai regex đó thành một regex duy nhất bằng cách sử dụng toán tử pipe (|). Tôi nghĩ rằng đoạn mã được viết rõ ràng hơn, nhưng nó chạy qua chuỗi hai lần, đó sẽ là một vấn đề nếu chuỗi nói chung là khá dài. (File đường dẫn thường là không, nhưng có thể được.)
Jon Watte

1
Tôi chỉ là nitpicking. Xin đừng coi trọng điều đó. Không cần phải tối ưu hóa, tất cả các giải pháp được đề xuất là quá đủ nhanh. Đường dẫn tệp rất dài vẫn là kilobyte, không phải gigabyte. Và chức năng này sẽ được kích hoạt một lần cho mỗi lần tải lên tệp, không phải 1000 lần trong một đợt. Điều quan trọng duy nhất ở đây là tính đúng đắn và rõ ràng của mã.
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ách xóa phần mở rộng


1
Điều này bỏ sót một phần quan trọng của câu hỏi, "chỉ giải nén tên tệp mà không có phần mở rộng". Nó sẽ giúp bạn đọc kỹ câu hỏi trước khi chuyển sang trả lời.
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

Không có câu trả lời nào ở trên phù hợp với tôi, đây là giải pháp của tôi giúp cập nhật đầu vào bị vô hiệu hóa với tên tệp:

<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

Nếu bạn đang sử dụng jQuery thì

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

val () thực sự sẽ trả về toàn bộ đường dẫn tệp mà anh ta không muốn.
FabricioG
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.