ค้นหาเว็บไซต์

javascript - วิธีเปิดหน้าต่างเลือกไฟล์ผ่าน js?


$('#id').click();

มันใช้งานไม่ได้บน Chrome 26 บน Mac OS

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

วิธีที่ง่ายคือการเพิ่มฟอร์มไฟล์เข้าไปในฟอร์มหลัก แต่ถูกห้ามไว้

คำตอบ #1

ใช้เฉพาะ JS - ไม่จำเป็นต้องใช้ jquery

เพียงสร้างองค์ประกอบอินพุตแล้วกระตุ้นการคลิก

var input = document.createElement('input');
input.type = 'file';
input.click();

นี่คือพื้นฐานที่สุด เปิดหน้าต่างเลือกไฟล์ แต่ไม่มีประโยชน์อะไรหากไม่จัดการกับไฟล์ที่เลือก...

การจัดการแฟ้ม

การเพิ่มเหตุการณ์ onchange ให้กับอินพุตที่สร้างขึ้นใหม่จะช่วยให้เราสามารถทำสิ่งต่างๆ ได้เมื่อผู้ใช้ได้เลือกไฟล์แล้ว

var input = document.createElement('input');
input.type = 'file';

input.onchange = e => { 
   var file = e.target.files[0]; 
}

input.click();

ในขณะนี้เรามีตัวแปรไฟล์ที่เก็บข้อมูลต่าง ๆ :

file.name // the file's name including extension
file.size // the size in bytes
file.type // file type ex. 'application/pdf'

เยี่ยม!

แต่ถ้าเราจำเป็นต้องใช้เนื้อหาของไฟล์ล่ะ?

เพื่อที่จะเข้าถึงเนื้อหาที่แท้จริงของไฟล์ ด้วยเหตุผลหลายประการ เช่น วางภาพ โหลดลงในแคนวาส สร้างหน้าต่างด้วย URL ข้อมูล Base64 เป็นต้น เราจำเป็นต้องใช้ API FileReader

เราจะสร้างอินสแตนซ์ของ FileReader และโหลดไฟล์ที่ผู้ใช้เลือกไปยังมัน

var input = document.createElement('input');
input.type = 'file';

input.onchange = e => { 

   // getting a hold of the file reference
   var file = e.target.files[0]; 

   // setting up the reader
   var reader = new FileReader();
   reader.readAsText(file,'UTF-8');

   // here we tell the reader what to do when it's done reading...
   reader.onload = readerEvent => {
      var content = readerEvent.target.result; // this is the content!
      console.log( content );
   }

}

input.click();

ลองวางโค้ดข้างต้นลงในหน้าต่างคอนโซลของเครื่องมือสำหรับนักพัฒนาของคุณ มันควรจะแสดงกล่องโต้ตอบเลือกไฟล์ หลังจากเลือกไฟล์แล้ว คอนโซลควรจะแสดงเนื้อหาของไฟล์นั้น

ตัวอย่าง - "ภาพพื้นหลังใหม่ของ Stackoverflow!"

ลองสร้างกล่องโต้ตอบการเลือกไฟล์เพื่อเปลี่ยนภาพพื้นหลังของ stackoverflow เป็นอะไรที่น่าตื่นเต้นมากขึ้น...

var input = document.createElement('input');
input.type = 'file';

input.onchange = e => { 

   // getting a hold of the file reference
   var file = e.target.files[0]; 

   // setting up the reader
   var reader = new FileReader();
   reader.readAsDataURL(file); // this is reading as data url

   // here we tell the reader what to do when it's done reading...
   reader.onload = readerEvent => {
      var content = readerEvent.target.result; // this is the content!
      document.querySelector('#content').style.backgroundImage = 'url('+ content +')';
   }

}

input.click();

เปิด devtools แล้ววางโค้ดด้านบนลงในหน้าต่างคอนโซล ซึ่งจะมีหน้าต่างเลือกไฟล์ปรากฏขึ้น เมื่อเลือกภาพ พื้นหลังของกล่องเนื้อหาบน Stackoverflow จะเปลี่ยนเป็นภาพที่เลือก

คำตอบ #2

การใช้ jQuery

ฉันจะสร้างปุ่มและอินพุตที่มองไม่เห็นดังนี้:

<button id="button">Open</button>
<input id="file-input" type="file" name="name" style="display: none;" />

และเพิ่ม jQuery บางส่วนเพื่อทริกเกอร์มัน:

$('#button').on('click', function() {
    $('#file-input').trigger('click');
});

การใช้ Vanilla JS

แนวคิดเดียวกัน แต่ไม่ใช้ jQuery (ขอบคุณ @Pascale):

<button onclick="document.getElementById('file-input').click();">Open</button>
<input id="file-input" type="file" name="name" style="display: none;" />

คำตอบ #3

ฟังก์ชันพร้อมใช้งาน (ใช้ Promise)

/**
 * Select file(s).
 * @param {String} contentType The content type of files you wish to select. For instance, use "image/*" to select all types of images.
 * @param {Boolean} multiple Indicates if the user can select multiple files.
 * @returns {Promise<File|File[]>} A promise of a file or array of files in case the multiple parameter is true.
 */
function selectFile(contentType, multiple){
    return new Promise(resolve => {
        let input = document.createElement('input');
        input.type = 'file';
        input.multiple = multiple;
        input.accept = contentType;

        input.onchange = () => {
            let files = Array.from(input.files);
            if (multiple)
                resolve(files);
            else
                resolve(files[0]);
        };

        input.click();
    });
}

ลองที่นี่

// Content wrapper element
let contentElement = document.getElementById("content");

// Button callback
async function onButtonClicked(){
    let files = await selectFile("image/*", true);
    contentElement.innerHTML = files.map(file => `<img src="${URL.createObjectURL(file)}" style="width: 100px; height: 100px;">`).join('');
}

// ---- function definition ----
function selectFile (contentType, multiple){
    return new Promise(resolve => {
        let input = document.createElement('input');
        input.type = 'file';
        input.multiple = multiple;
        input.accept = contentType;

        input.onchange = _ => {
            let files = Array.from(input.files);
            if (multiple)
                resolve(files);
            else
                resolve(files[0]);
        };

        input.click();
    });
}
<button onclick="onButtonClicked()">Select images</button>
<div id="content"></div>

คำตอบ #4

ใน HTML เท่านั้น:

<label>
  <input type="file" name="input-name" style="display: none;" />
  <span>Select file</span>
</label>

ตรวจสอบฟิดเดิลนี้กับโค้ดด้านบน

คำตอบ #5

เพื่อความครบถ้วน สมบัติของ Ron van der Heijden ในรูปแบบ JavaScript ล้วน:

<button onclick="document.querySelector('.inputFile').click();">Select File ...</button>
<input class="inputFile" type="file" style="display: none;">

คำตอบ #6

เพื่อขยายคำตอบจาก 'levi' และเพื่อแสดงวิธีการรับการตอบกลับจากการอัปโหลดเพื่อให้คุณสามารถประมวลผลการอัปโหลดไฟล์ได้:

selectFile(event) {
    event.preventDefault();

    file_input = document.createElement('input');
    file_input.addEventListener("change", uploadFile, false);
    file_input.type = 'file';
    file_input.click();
},

uploadFile() {
    let dataArray = new FormData();
    dataArray.append('file', file_input.files[0]);

    // Obviously, you can substitute with JQuery or whatever
    axios.post('/your_super_special_url', dataArray).then(function() {
        //
    });
}

บทความที่เกี่ยวข้อง