เนื้อหานี้จะพามาดูแนวทางการสร้างวิธีการลากไฟล์มาวางในพื้นที่ที่กำหนดแล้วให้ทำการ
อัพโหลดไฟล์นั้นๆ หรือที่เรียกว่าการอัพโหลดไฟล์แบบ 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>