เขียนโดย
Thanawat Udchachon
Internship @ borntoDev
Cloudinary คืออะไร
ก่อนอื่นก่อนใดเลยเรามารู้จักกับ Cloudinary กันก่อนดีกว่า Cloudinary เนี่ยเป็นแพลตฟอร์มสำหรับเก็บไฟล์ประเภทสื่อ เช่น ภาพ วิดีโอ ซึ่งก็เจ้านี่แหละ ที่เราจะใช้ในการฝากไฟล์ภาพของเรากัน ว่าแล้วเราก็มาดูบนหน้า dashboard กันเลยก่อนดีกว่า
จะเห็นได้ว่าจะมีข้อมูลต่าง ๆ อย่าง Cloud Name, API Key, API Secret, API Environment variable ซึ่งข้อมูลเหล่านี้แหละ ที่เราจะนำไปใช้ในโปรเจกต์ของเรา แต่ก่อนเราจะไปเริ่มเขียนโค้ดกัน เรามาสร้าง preset กันก่อนดีกว่า โดยเจ้า preset เนี่ย มันเป็นเหมือนการตั้งค่าสำหรับการอัปโหลดภาพให้เหมาะกับงานของเราแต่ละงาน อ่ะ เราไปลองสร้างดูกันก่อนดีกว่า
สร้าง preset สำหรับการอัปโหลดภาพ
ให้เรากดที่ปุ่ม settings ด้านขวาบนแล้วก็ไปที่แถบ Upload แล้วเลื่อนลงมาก็จะเจอกับ Upload presets แล้วก็ให้เรากด Add upload preset
สำหรับ preset นี้เนี่ย ผมจะทำเป็น preset สำหรับ upload ภาพโปรไฟล์ละกัน

ส่วนหลัก ๆ ที่เราจะตั้งค่ากันเนี่ยก็คือชื่อของ preset ในที่นี้ก็จะเป็น profile_pic แล้วก็ชื่อ folder ซึ่งก็จะเป็น profile_pic เหมือนกัน ซึ่ง folder ที่ว่าเนี่ยมันคือที่เก็บไฟล์ ซึ่งก็อยู่บน Cloudinary นี่แหละ แล้วก็อีกส่วนก็คือ Overwrite ในที่นี้จะตั้งเป็น on ไว้เพราะภาพโปรไฟล์เก่าก็จะไม่ถูกใช้อยู่แล้ว เราก็เลยให้เวลาอัปภาพโปรไฟล์ใหม่ขึ้นมาจะให้ไปทับภาพเดิมเลย
มาเริ่มเขียนโค้ดกันเลยดีกว่า
สำหรับตัวอย่างโค้ดจะขอใช้เป็น React.js แล้วก็ Express.js สำหรับบันทึกที่อยู่ไฟล์ลง database นะครับ
เอาล่ะอันดับแรกเรามาดูโค้ดตั้งต้นกันก่อนดีกว่า
import React from 'react';
export default function Upload() {
return (
<div>
<form>
<input
type="file"
/>
<button type="submit">
submit
</button>
</form >
</div >
)
}
ซึ่งโค้ดนี้ก็เป็นการแสดงปุ่มเลือกไฟล์ที่เลือกไฟล์ไปแล้วก็ยังทำอะไรต่อไม่ได้กับปุ่ม submit เปล่า ๆ นะครับ

ต่อมาเรามาเขียนฟังก์ชันรับไฟล์ภาพกัน
โดยฟังก์ชันเราก็จะไม่ได้มีอะไรซับซ้อนโดยเราจะให้เมื่อเลือกไฟล์แล้วจะให้ไฟล์ภาพนั้นไปเก็บไว้ใน state แล้วเมื่อกดปุ่ม submit ก็จะส่งไฟล์ที่อยู่ใน state ไปที่ back-end ผ่าน axios นั้นเอง
import React, { useState } from 'react';
import Axios from 'axios';
export default function Upload() {
Axios.defaults.withCredentials = true;
const [imageFile, setImageFile] = useState('');
const handleFileInputChange = (e) => {
const file = e.target.files[0];
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend = () => {
setImageFile(reader.result);
}
}
const handleSubmitFile = (e) => {
e.preventDefault();
if (!imageFile) return;
Axios.put(`api url`, { data: imageFile});
}
return (
<div>
<form onSubmit={handleSubmitFile}>
<input
type="file"
onChange={handleFileInputChange}
/>
<button type="submit">
submit
</button>
</form >
</div >
)
}
โดยในส่วนของ api url นี้จะเป็น url ของ back-end ของเราหรือจะเป็น url ของ Cloudinary เลยก็ได้ ซึ่งจะเป็นลิงก์แบบนี้ httpsุ://api.cloudinary.com/v1_1/(Cloud Name ของ Cloudinary)/upload
แต่เราจะต้องใส่ข้อมูล key อื่น ๆ ของ Cloudinary ไปด้วย แต่ในที่นี้เราจะไปเขียนกันใน back-end แต่ก่อนอื่นเรามาติดตั้งเจ้า cloudinary กันก่อนดีกว่า ซึ่งก็สามารถเข้าไปในลิงก์ต่อไปนี้ได้เลยครับ https://www.npmjs.com/package/cloudinary
เอาล่ะแล้วเราก็มาโผล่บน express.js ของเรากัน
router.use(express.json({ limit: '50mb' }));
router.use(express.urlencoded({ limit: '50mb', extended: true }));
const { cloudinary } = require('../utils/cloudinary');
router.put('/upload', async (req, res) => {
try {
const user = req.session.user[0];
const fileStr = req.body.data;
const uploadedResponse = await
cloudinary.uploader.upload(fileStr, {
upload_preset: 'profile_pic',
public_id: `${user.userId}`
});
console.log(uploadedResponse);
const url = uploadedResponse.url;
var sql = `UPDATE Users SET imgProfile="${url}"
WHERE userId = ${user.userId}`;
db.query(sql, (err, result) => {
if (err) {
console.log(err);
} else {
console.log(result);
}
});
res.json({ msg: 'Upload complete' });
} catch (error) {
console.error(error);
res.status(500).json({ err: 'Something went wrong' })
}
});
อันนี้ก็จะเป็นตัวอย่างโค้ด back-end ของการอัปโหลดรูปภาพขึ้น Cloudinary โค้ดอาจจะดูเยอะไปสักหน่อย ซึ่งจริง ๆ ตัวสำคัญมันก็ไม่ได้มีเยอะอะไร ว่าแล้วก็มาอธิบายโค้ดกันสักหน่อยดีกว่า
ส่วนแรกเลยคือเจ้า {cloudinary} จะเป็นตัวที่เก็บข้อมูลต่าง ๆ สำหรับ cloudinary ไว้เช่น key ต่าง ๆ
โดยเราจะตั้งชื่อเจ้าไฟล์นี้กันว่า cloudinary.js ซึ่งมีหน้าตาโค้ดดังนี้
require('dotenv').config();
const cloudinary = require('cloudinary').v2;
cloudinary.config({
cloud_name: process.env.CLOUDINARY_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET,
});
module.exports = { cloudinary };
ซึ่งที่จริงแล้วเราสามารถนำ key ต่าง ๆ ของ cloudinary มาพิมพ์ใส่ตรง ๆ เลยก็ได้ แต่เพื่อความปลอดภัย แนะนำว่าเก็บไว้ใน .env จะดีกว่า โดยการจะใช้ .env ขอแนะนำเจ้า dotenv ซึ่งก็สามารถไปติดตั้งกันได้ตามลิงก์นี้เลยครับ https://www.npmjs.com/package/dotenv
ต่อมานะครับ อย่างที่บอกไปก่อนหน้านี้ว่าเราจะทำระบบอัปโหลดรูปโปรไฟล์กัน ดังนั้น method ที่เราจะใช้จะเป็น PUT เพื่อไปแก้ลิงก์รูปโปรไฟล์ใน database นะครับ แต่ถ้าหากเพื่อนอยากจะทำระบบอัปโหลดภาพโดยไม่ต้องไปแก้ข้อมูลที่มีอยู่แล้วใน database ก็สามารถใช้เป็น method POST ได้เลยครับผม โดยการทำงานของมันหลัก ๆ นะครับมันก็จะส่งข้อมูลไปตามข้อมูลที่เราใส่ไว้ใน cloudinary.js โดยเป็น preset profile_pic ตามที่เราได้ตั้งค่าไว้ก่อนหน้านี้ และตั้งชื่อไฟล์ตาม userId ของระบบเรา เพื่อที่ว่าถ้า user ของเว็บไซต์เราได้ทำการอัปโหลดภาพโปรไฟล์ใหม่จะได้ไปทับโปรไฟล์เดิมของเขาบน cloudinary เลย
และหลังจากที่อัปโหลดไปแล้วเราจะได้ response กลับมา โดยเราสามารถดูได้จาก console.log(uploadedResponse) ซึ่งในนั้นก็จะมี url ซึ่งเป็นลิงก์ของภาพที่เราได้ทำการอัปโหลดขึ้นไป แล้วเราก็ทำการบันทึกลิงก์ดังกล่าวลงไปใน database ของเราสำหรับการเรียกแสดง
โดยภาพที่เราทำการอัปโหลดก็จะมาโผล่เป็นเว็บไซต์ Cloudinary ในส่วนของ Media Library ตามนี้เลย

สรุปสุดท้ายสิ่งที่ผู้อ่านจะได้รับ
เป็นยังไงกันบ้างครับสำหรับระบบอัปโหลดรูปภาพและเก็บไฟล์ด้วย Cloudinary อยากจะลองให้ลองไปเล่น preset กันดู โดยนอกจากการรับอัปโหลดที่ละไฟล์แล้วมันยังสามารถอัปทีละหลายไฟล์หรือตั้งไม่ให้ทับไฟล์เก่าและอีกมากมายครับ และก็เพิ่มเติมสำหรับเพื่อน ๆ ที่ไม่อยากให้เป็นปุ่มอัปโหลดแต่อยากให้สามารถลากวางไฟล์ได้เลยก็ขอแนะนำเจ้า Dropzone ซึ่งสามารถติดตั้งได้ที่ลิงก์นี้ได้เลยครับ https://www.npmjs.com/package/dropzone
อ้างอิงจาก
- Cloudinary Image Upload with Nodejs and React, สืบค้นเมื่อ 27 มกราคม 2565 จาก: https://www.youtube.com/watch?v=Rw_QeJLnCK4&t=849s
- Image Uploads to Cloudinary in React with Drag & Drop, สืบค้นเมื่อ 27 มกราคม 2565 จาก: https://www.youtube.com/watch?v=V8w7K1HdrFo&t=404s




