เนื้อหานี้จะพามาดูแนวทางการสร้างวิธีการลากไฟล์มาวางในพื้นที่ที่กำหนดแล้วให้ทำการ
อัพโหลดไฟล์นั้นๆ หรือที่เรียกว่าการอัพโหลดไฟล์แบบ drag and drop โดยคำสั่งเกี่ยวกับ
การจัดการวิธีการอัพโหลด เราจะใช้ javascript และในส่วนของคำสั่งทำการอัพโหลดไฟล์ฝั่ง
server เราจะใช้เป็นฟังก์ชั่น php อย่างเเกี่ยวกับการอัพโหลดไฟล์อย่างง่าย
1. สร้างส่วนของการกำหนดพื้นที่ของตำแหน่งที่เราจะให้สามารถลากไฟล์มาวาง
<style> .drop-place{ margin: auto; width: 75%; height: 50px; border: 1px solid red; text-align: center; padding: 50px; font-size: 20px; } .drop-place.dragging{ background: #C8EFD4; } .drop-place.dropped{ background: #6BD089; } .drop-guide.process{ color: yellow; } .drop-guide.success{ color: blue; } </style> <div class="drop-place"> <span class="drop-guide">ลากไฟล์มาวางที่นี่เพื่ออัพโหลด</span> </div>
2. กำหนดส่วนของ javascript ในการทำงานเมื่อมีการลากไฟล์เข้ามาในพื้นที่ เบื้องต้นจะให้เห็น
รูปแบบการทำงานของเหตุการณ์ต่างๆ ที่จะเกิดขึ้นสำหรับการลากไฟล์มาในพื้นที่เพื่ออัพโหลด
<script> document.addEventListener("DOMContentLoaded", (event) => { console.log("DOM fully loaded and parsed"); const el = document.querySelector(".drop-place"); const drop_guide = document.querySelector(".drop-guide"); // เมื่อลากไฟล์เข้ามาในพื้นที่ ทำงานครั้งเดียวเมื่อลากไฟล์เข้ามา el.addEventListener("dragenter", (event) => { event.preventDefault(); console.log("DragEnter"); drop_guide.textContent = 'ปล่อยไฟล์เพื่ออัพโหลด'; // var drag_image = event.originalEvent.dataTransfer.files; }); // เมื่อลากไฟล์เข้ามาอยู่ด้านบนของพื้นที่ ส่วนนี้จะทำงานตลอดที่ไฟล์ที่ลากยังอยู่ในพื้ที่ el.addEventListener("dragover", (event) => { event.preventDefault(); console.log("DragOver"); event.target.classList.add('dragging'); }); // เมื่อนำไฟล์ที่ลากออกนอกพื้นที่ จะทำงานครั้งเดียวเมื่่อลากไฟล์ออกนอกพื้นที่ el.addEventListener("dragleave", (event) => { event.preventDefault(); console.log("DragLeave"); drop_guide.textContent = 'ลากไฟล์มาวางที่นี่เพื่ออัพโหลด'; event.target.classList.remove('dragging'); }); // เมื่อวางหรือปล่อยไฟล์ที่ลากลงในพื้นที่ ทำงานครั้งเดียว el.addEventListener("drop", (event) => { event.preventDefault(); console.log("Drop"); drop_guide.textContent = 'กำลังอัพโหลดไฟล์...'; event.target.classList.remove('dragging'); event.target.classList.add('dropped'); }); }); </script>
3. โฟกัสในส่วนของการ drop ไฟล์
// เมื่อวางหรือปล่อยไฟล์ที่ลากลงในพื้นที่ ทำงานครั้งเดียว el.addEventListener("drop", (event) => { event.preventDefault(); console.log("Drop"); drop_guide.textContent = 'กำลังอัพโหลดไฟล์...'; event.target.classList.remove('dragging'); event.target.classList.add('dropped'); // ตัวแปรเก็บข้อมูลไฟล์ ที่ลากมาวางเพื่ออัพโหลด var image = event.dataTransfer.files; console.log(image); });
เมื่อมีการวางไฟล์เพื่อทำการอัพโหลด เราสามารถดูข้อมูล FileList ที่นำมาวาง ผ่านค่า
event.dataTransfer.files ซึ่งจะเป็นข้อมูลไฟล์อาเรย์ นั่นหมายความว่า เราสามารถลาก
มาวางทีละหลายๆ ไฟล์พร้อมกันได้ แต่ในตัวอย่างนี้เราจะอัพโหลดแค่ไฟล์เดียวก่อน
เมื่อเราได้ข้อมูลไฟล์รูปที่จะอัพโหลด ต่อไป เราต้องทำการสร้างฟอร์มข้อมูล ในที่นี้ก็คือ
ข้อมูล FormData object โดยสร้าง ตัวแปร สำหรับเก็บข้อมูลดังนี้
var formData = new FormData();
ถ้าเรานึกภาพไม่ออกว่าข้อมูล FormData คืออะไร ให้เรานึกถึงรูปแบบฟอร์มส่งข้อมูลทั่วไป
<form action="" method="post"> <input type="text"> <button type="submit">Send</button> </form>
ข้างต้นคือรูปแบบฟอร์มที่สร้างด้วย html แต่การสร้างด้วย javascript จะใช้เป็น new FormData();
ซึ่งจะเป็นการสร้างแค่ฟอร์มข้อมูล ยังไม่มี Element หรือฟิลด์ข้อมูลใดๆ เช่นตัวอย่างด้านบน จะมี input
text เป็นองค์ประกอบ ดังนั้น คำสั่งที่จะเพิ่มองค์ประกอบ หรือ Element ของฟอร์มจะใช้เป็น
var formData = new FormData(); formData.append('picture', image[0]);
เรากำหนดชื่อฟิลด์เป็น picture เนื่องจากข้อมูลจากตัวแปร image ของเราเป็นอาเรย์รูปภาพ
ตัวแปรข้อมูลที่ส่งไปก็จะเป็น $_FILES['picture'] และเมื่อเรา จะเลือกเพียงไฟล์เดียว จึงกำหนดเป็นค่า
ที่อาเรย์ 0 หรือค่าแรก เป็น image[0] เป็นค่ารุปภาพที่เรากำหนดให้ตัวแปร $_FILES['picture']
4. เมื่อเราได้ข้อมูลฟอร์มสำหรับส่งเรียบร้อยแล้ว ต่อไปก็คือการสร้างฟังก์ชั่น ajax สำหรับการส่งข้อมูล
ในที่นี้เราจะใช้คำสั่ง fetch() ซึ่งคำสั่งนี้เป็นคำสั่งที่มีเรื่องของเวลาที่ต้องรอเข้ามาเกี่ยวข้อง เพราะเป็น
การส่งข้อมูลไปยัง server และต้องรอการทำงาน หรือก็คือการทำงานแบบ async (asynchronous)
// ฟังก์ชั่่ง ajax ส่งข้อมูลไปยัง server และต้องรอข้อมูลกลับมาก่อนนำไปใช้งาน async function uploadFormData(formData) { const response_async = await fetch('upload.php?upload', { method: "POST", body: formData // ส่งข้อมูลฟอร์ม }); // เพื่อให้ข้อมูลที่ส่งกลับมา สามารถนำไปประยุกต์ใช้ได้ เราจึงให้ส่งเป็น json object return response_async.json(); }
5. เรียกใช้ฟังก์ชั่น ajax สำหรับอัพโหลดหรือส่งข้อมูลไปยัง server เมื่อเราได้ฟังก์ชั่นสำหรับส่งข้อมูล
แล้ว ในการเรียกใช้ฟังก์ชั่น async ก็จะต้องรอข้อมูลส่งกลับมาก่อนถึงจะนำไปประมวลผลหรือทำงานต่อ
ดังนั้นวิธีการใช้งานจะเป็นในรูปแบบดังนี้
uploadFormData(formData) // ส่งข้อมูลไปัยัง server .then( response => { // เมื่อส่งข้อมูลกลับมา console.log( response ); // JSON data if(response.status=="OK"){ event.target.classList.remove('dropped'); drop_guide.classList.remove('process'); drop_guide.classList.add('success'); drop_guide.textContent = 'อัพโหลดไฟล์เรียบร้อยแล้ว'; setTimeout(()=>{ drop_guide.textContent = 'ลากไฟล์มาวางที่นี่เพื่ออัพโหลด'; drop_guide.classList.remove('success'); },2000); } });
6. ส่วนของไฟล์สำหรับอัพโหลดในฝั่งของ server อย่างง่าย สามารถประยุกต์เพิ่มเติมได้ตามต้องการ
ไฟล์ upload.php
<?php if(isset($_GET['upload'])){ if (!empty($_FILES['picture'])) { if (is_uploaded_file($_FILES['picture']['tmp_name'])) { $sourcePath = $_FILES['picture']['tmp_name']; $targetPath = "uploads/" . $_FILES['picture']['name']; if (move_uploaded_file($sourcePath, $targetPath)) { $response = array( "status"=>"OK" ); }else{ $response = array( "status"=>"Fail" ); } }else{ $response = array( "status"=>"Fail" ); } }else{ $response = array( "status"=>"Fail" ); } header("Content-Type: application/json"); echo json_encode($response); exit; } ?>
ตัวอย่างไฟล์ทดสอบ ajax_draganddrop.php ทั้งหมด
<?php if(isset($_GET['upload'])){ if (!empty($_FILES['picture'])) { if (is_uploaded_file($_FILES['picture']['tmp_name'])) { $sourcePath = $_FILES['picture']['tmp_name']; $targetPath = "uploads/" . $_FILES['picture']['name']; if (move_uploaded_file($sourcePath, $targetPath)) { $response = array( "status"=>"OK" ); }else{ $response = array( "status"=>"Fail" ); } }else{ $response = array( "status"=>"Fail" ); } }else{ $response = array( "status"=>"Fail" ); } header("Content-Type: application/json"); echo json_encode($response); exit; } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <style> .drop-place{ margin: auto; width: 75%; height: 50px; border: 1px solid red; text-align: center; padding: 50px; font-size: 20px; } .drop-place.dragging{ background: #C8EFD4; } .drop-place.dropped{ background: #6BD089; } .drop-guide.process{ color: yellow; } .drop-guide.success{ color: blue; } </style> <div class="drop-place"> <span class="drop-guide">ลากไฟล์มาวางที่นี่เพื่ออัพโหลด</span> </div> <script> document.addEventListener("DOMContentLoaded", (event) => { console.log("DOM fully loaded and parsed"); const el = document.querySelector(".drop-place"); const drop_guide = document.querySelector(".drop-guide"); // เมื่อลากไฟล์เข้ามาในพื้นที่ ทำงานครั้งเดียวเมื่อลากไฟล์เข้ามา el.addEventListener("dragenter", (event) => { event.preventDefault(); // console.log("DragEnter"); drop_guide.textContent = 'ปล่อยไฟล์เพื่ออัพโหลด'; // var drag_image = event.originalEvent.dataTransfer.files; }); // เมื่อลากไฟล์เข้ามาอยู่ด้านบนของพื้นที่ ส่วนนี้จะทำงานตลอดที่ไฟล์ที่ลากยังอยู่ในพื้ที่ el.addEventListener("dragover", (event) => { event.preventDefault(); // console.log("DragOver"); event.target.classList.add('dragging'); }); // เมื่อนำไฟล์ที่ลากออกนอกพื้นที่ จะทำงานครั้งเดียวเมื่่อลากไฟล์ออกนอกพื้นที่ el.addEventListener("dragleave", (event) => { event.preventDefault(); // console.log("DragLeave"); drop_guide.textContent = 'ลากไฟล์มาวางที่นี่เพื่ออัพโหลด'; event.target.classList.remove('dragging'); }); // เมื่อวางหรือปล่อยไฟล์ที่ลากลงในพื้นที่ ทำงานครั้งเดียว el.addEventListener("drop", (event) => { event.preventDefault(); console.log("Drop"); drop_guide.textContent = 'กำลังอัพโหลดไฟล์...'; drop_guide.classList.add('process'); event.target.classList.remove('dragging'); event.target.classList.add('dropped'); // ตัวแปรเก็บข้อมูลไฟล์ ที่ลากมาวางเพื่ออัพโหลด var image = event.dataTransfer.files; var formData = new FormData(); console.log(image); formData.append('picture', image[0]); uploadFormData(formData) // ส่งข้อมูลไปัยัง server .then( response => { // เมื่อส่งข้อมูลกลับมา console.log( response ); // JSON data if(response.status=="OK"){ event.target.classList.remove('dropped'); drop_guide.classList.remove('process'); drop_guide.classList.add('success'); drop_guide.textContent = 'อัพโหลดไฟล์เรียบร้อยแล้ว'; setTimeout(()=>{ drop_guide.textContent = 'ลากไฟล์มาวางที่นี่เพื่ออัพโหลด'; drop_guide.classList.remove('success'); },2000); } }); }); // ฟังก์ชั่่ง ajax ส่งข้อมูลไปยัง server และต้องรอข้อมูลกลับมาก่อนนำไปใช้งาน async function uploadFormData(formData) { const response_async = await fetch('ajax_draganddrop.php?upload', { method: "POST", body: formData // ส่งข้อมูลฟอร์ม }); // เพื่อให้ข้อมูลที่ส่งกลับมา สามารถนำไปประยุกต์ใช้ได้ เราจึงให้ส่งเป็น json object return response_async.json(); } }); </script> </body> </html>