เนื้อหานี้จะพามาดูแนวทางการสร้างวิธีการลากไฟล์มาวางในพื้นที่ที่กำหนดแล้วให้ทำการ
อัพโหลดไฟล์นั้นๆ หรือที่เรียกว่าการอัพโหลดไฟล์แบบ drag and drop โดยคำสั่งเกี่ยวกับ
การจัดการวิธีการอัพโหลด เราจะใช้ javascript และในส่วนของคำสั่งทำการอัพโหลดไฟล์ฝั่ง
server เราจะใช้เป็นฟังก์ชั่น php อย่างเเกี่ยวกับการอัพโหลดไฟล์อย่างง่าย
1. สร้างส่วนของการกำหนดพื้นที่ของตำแหน่งที่เราจะให้สามารถลากไฟล์มาวาง
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <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 ในการทำงานเมื่อมีการลากไฟล์เข้ามาในพื้นที่ เบื้องต้นจะให้เห็น
รูปแบบการทำงานของเหตุการณ์ต่างๆ ที่จะเกิดขึ้นสำหรับการลากไฟล์มาในพื้นที่เพื่ออัพโหลด
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | <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 ไฟล์
1 2 3 4 5 6 7 8 9 10 11 | // เมื่อวางหรือปล่อยไฟล์ที่ลากลงในพื้นที่ ทำงานครั้งเดียว 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 โดยสร้าง ตัวแปร สำหรับเก็บข้อมูลดังนี้
1 | var formData = new FormData(); |
ถ้าเรานึกภาพไม่ออกว่าข้อมูล FormData คืออะไร ให้เรานึกถึงรูปแบบฟอร์มส่งข้อมูลทั่วไป
1 2 3 4 | <form action= "" method= "post" > <input type= "text" > <button type= "submit" >Send</button> </form> |
ข้างต้นคือรูปแบบฟอร์มที่สร้างด้วย html แต่การสร้างด้วย javascript จะใช้เป็น new FormData();
ซึ่งจะเป็นการสร้างแค่ฟอร์มข้อมูล ยังไม่มี Element หรือฟิลด์ข้อมูลใดๆ เช่นตัวอย่างด้านบน จะมี input
text เป็นองค์ประกอบ ดังนั้น คำสั่งที่จะเพิ่มองค์ประกอบ หรือ Element ของฟอร์มจะใช้เป็น
1 2 | var formData = new FormData(); formData.append( 'picture' , image[0]); |
เรากำหนดชื่อฟิลด์เป็น picture เนื่องจากข้อมูลจากตัวแปร image ของเราเป็นอาเรย์รูปภาพ
ตัวแปรข้อมูลที่ส่งไปก็จะเป็น $_FILES['picture'] และเมื่อเรา จะเลือกเพียงไฟล์เดียว จึงกำหนดเป็นค่า
ที่อาเรย์ 0 หรือค่าแรก เป็น image[0] เป็นค่ารุปภาพที่เรากำหนดให้ตัวแปร $_FILES['picture']
4. เมื่อเราได้ข้อมูลฟอร์มสำหรับส่งเรียบร้อยแล้ว ต่อไปก็คือการสร้างฟังก์ชั่น ajax สำหรับการส่งข้อมูล
ในที่นี้เราจะใช้คำสั่ง fetch() ซึ่งคำสั่งนี้เป็นคำสั่งที่มีเรื่องของเวลาที่ต้องรอเข้ามาเกี่ยวข้อง เพราะเป็น
การส่งข้อมูลไปยัง server และต้องรอการทำงาน หรือก็คือการทำงานแบบ async (asynchronous)
1 2 3 4 5 6 7 8 9 | // ฟังก์ชั่่ง 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 ก็จะต้องรอข้อมูลส่งกลับมาก่อนถึงจะนำไปประมวลผลหรือทำงานต่อ
ดังนั้นวิธีการใช้งานจะเป็นในรูปแบบดังนี้
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <?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 ทั้งหมด
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | <?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> |