Javascript - วิธีแยกชื่อไฟล์จากตัวควบคุมอินพุตไฟล์


118

เมื่อผู้ใช้เลือกไฟล์ในเว็บเพจฉันต้องการที่จะสามารถแยกเฉพาะชื่อไฟล์

ฉันได้ลองฟังก์ชั่น str.search แต่ดูเหมือนว่าจะล้มเหลวเมื่อชื่อไฟล์เป็นอะไรเช่นนี้C: \ อัปโหลด \ ilike.this.file.jpg

เราจะแยกเฉพาะชื่อไฟล์ที่ไม่มีนามสกุลได้อย่างไร?

คำตอบ:


128

สมมติว่า<input type = "file"> ของคุณมี id ของการอัปโหลดหวังว่าจะทำเคล็ดลับได้:

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 และอื่น ๆ
Yeti

1
จะรับชื่อไฟล์ในกรณีที่เลือกหลายไฟล์ได้อย่างไร?
avngr

ทำไมไม่คำนวณ startIndex แบบนั้นล่ะ var startIndex = Math.max(fullPath.lastIndexOf('\\'), fullPath.lastIndexOf('/')) + 1;
nollidge

197

ในการแยกสตริง ({filepath} / {filename}) และรับชื่อไฟล์คุณสามารถใช้ดังนี้:

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

"วิธีการป๊อปจะลบองค์ประกอบสุดท้ายออกจากอาร์เรย์และส่งคืนค่านั้นให้กับผู้เรียก"
Mozilla Developer Network

ตัวอย่าง:

จาก: "/home/user/file.txt".split(/(\\|\/)/g).pop()

คุณได้รับ: "file.txt"


5
คุณสามารถทำได้ด้วย regexes และไม่ต้องดำเนินการอาร์เรย์ใด ๆ :var filename = filepath.replace(/^.*?([^\\\/]*)$/, '$1');
vog

1
คำตอบของ vog นั้นใกล้เคียงกับคำตอบที่ถูกต้อง 100% จริงๆสำหรับคำถาม (ยกเว้นต้องตัดส่วนขยายออก) ชื่อไฟล์ก็ไม่ต่างจากสตริงอื่น ๆ
Jon Watte

1
regex แยกสามารถย่อให้สั้นลง[\\/]ได้ นอกจากนี้ยังมีการขอให้แยกนามสกุลไฟล์ด้วย สำหรับวิธีแก้ปัญหาที่สมบูรณ์โปรดดู: stackoverflow.com/a/32156800/19163
vog

หลายแพลตฟอร์มรัดกุม ยิ่งใหญ่
Marc

ทางออกที่ดีฉันไม่เข้าใจว่ามันทำงานอย่างไรและนั่นคือเหตุผลที่ชอบมากกว่านี้!
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

ในกรณีที่คุณใช้ TypeScript แล้วมันคือ $ ("# fileupload") [0] ["files"] [0];
Morvael

19

สมมติว่า:

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

JavaScript จะเป็น:

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

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

ถือว่าผู้ใช้กำลังเรียกใช้ Windows ระบบปฏิบัติการอื่นใช้ตัวแยกเส้นทางไฟล์ที่แตกต่างกัน
Quentin

คุณจำเป็นต้องตรวจสอบอักขระ "/" สำหรับผู้ใช้ที่ไม่ใช่ Windows เช่น if (! pieces) {str.split ('/'); }? วิธีง่ายๆที่ดีแม้ว่า +1
Ian Oxley

IIRC, IE เป็นเบราว์เซอร์เดียวที่ให้เส้นทางเต็มของไฟล์อย่างไรก็ตามคุณไม่จำเป็นต้องแยกบนเบราว์เซอร์อื่น ๆ เช่น Firefox ดังนั้นจึงยังใช้งานได้ แม้ว่าฉันจะยอมรับว่าฉันไม่ได้ลองใช้เบราว์เซอร์ linux / unix ทุกตัว
TM.

6
str.split (/ (\\ | \ /) / g); สำหรับ windows และ * nix
Tracker1

@TM Chrome ใช้ตัวแปรเส้นทางปลอมเพื่อความปลอดภัยซึ่งน่าเกลียด iirc มันแตกต่างกันไปขึ้นอยู่กับระบบปฏิบัติการที่คุณใช้
lededje

5

ผมถือว่าคุณต้องการที่จะตัดส่วนขยายทั้งหมดคือการ/tmp/test/somefile.tar.gzsomefile

แนวทางโดยตรงกับ regex:

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

แนวทางทางเลือกที่มีการดำเนินการ regex และอาร์เรย์:

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

1
สิ่งนี้ไม่ได้ตัดส่วนขยายออกตามที่ขอ
Jon Watte

แก้ไขแล้ว. ขอบคุณสำหรับคำแนะนำ!
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'

จากผลการทดสอบคุณจะเห็นว่าฟังก์ชันนี้ทำงานได้ค่อนข้างดีเมื่อเทียบกับวิธีการอื่น ๆ ที่เสนอไว้ที่นี่

หมายเหตุสำหรับมือใหม่เกี่ยวกับ \\: \ คืออักขระหลีกเช่น \ n หมายถึงบรรทัดใหม่และแท็บ \ ta เพื่อให้สามารถเขียนได้ \ n คุณต้องพิมพ์ \\ n


1
ระวังเส้นทางนี้: dir.with.dots / fileWithoutDotsเนื่องจากคุณจะได้รับ eOffset น้อยกว่า nOffset และสับสนกับนิพจน์การแยก
Jesse Chisholm

ใช่แก้ไขแล้ว ตอนนี้ก็ควรจะทำงานได้อย่างถูกต้องเช่นกัน (เพิ่ม&& eOffset < nOffset)
เยติ

2

อินพุต : C:\path\Filename.ext
เอาต์พุต :Filename

ในโค้ด HTML ตั้งค่า File เป็นonChangeแบบนี้ ...

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

1

คำตอบที่ได้รับการโหวตสูงทั้งสองไม่ได้ให้ "เพียงชื่อไฟล์ที่ไม่มีนามสกุล" และวิธีแก้ปัญหาอื่น ๆ นั้นมีรหัสมากเกินไปสำหรับงานง่ายๆเช่นนี้

ฉันคิดว่านี่ควรเป็นซับเดียวสำหรับโปรแกรมเมอร์ JavaScript ทุกคน มันเป็นนิพจน์ทั่วไปที่ง่ายมาก:

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

ขั้นแรกให้ตัดอะไรก็ได้จนถึงเครื่องหมายทับสุดท้ายถ้ามี

จากนั้นให้ตัดสิ่งใด ๆ ออกหลังจากช่วงเวลาสุดท้ายถ้ามี

มันง่ายมันแข็งแกร่งมันใช้สิ่งที่ขอ ฉันพลาดอะไรไปรึเปล่า?


1
"นิพจน์ทั่วไปที่เรียบง่ายมาก" ... อันที่จริงนี่คือนิพจน์สองตัว :-) ดูคำตอบของฉันสำหรับโซลูชัน regex เดียว
vog

ใช่นอกจากนี้ยังมีการเขียนซ้ำที่ชัดเจนเพื่อบรรจุ regexes ทั้งสองลงใน regex เดียวโดยใช้ตัวดำเนินการไปป์ (|) ฉันคิดว่าโค้ดตามที่เขียนนั้นชัดเจนกว่า แต่มันทำงานผ่านสตริงสองครั้งซึ่งจะเป็นปัญหาหากสตริงโดยทั่วไปค่อนข้างยาว (โดยทั่วไปเส้นทางของไฟล์ไม่ใช่ แต่สามารถเป็นได้)
Jon Watte

1
ฉันแค่คิดสั้น โปรดอย่าจริงจังกับเรื่องนั้น ไม่จำเป็นต้องปรับให้เหมาะสมโซลูชันที่นำเสนอทั้งหมดนั้นเร็วเกินพอ เส้นทางไฟล์ที่ยาวมากยังคงเป็นกิโลไบต์ไม่ใช่กิกะไบต์ และฟังก์ชันนี้จะถูกทริกเกอร์หนึ่งครั้งต่อการอัปโหลดไฟล์ไม่ใช่ 1000x ในชุดงาน สิ่งเดียวที่สำคัญที่นี่คือความถูกต้องและความชัดเจนของรหัส
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
}

วิธีลบส่วนขยาย


1
สิ่งนี้ขาดส่วนสำคัญของคำถาม "แยกเฉพาะชื่อไฟล์ที่ไม่มีนามสกุล" ช่วยให้อ่านคำถามอย่างรอบคอบก่อนที่จะกระโดดเพื่อตอบคำถาม
zeh


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>

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.