DigitalOcean Spaces คืออะไร?
DigitalOcean Spaces คือบริการ Object Storage ที่เข้ากันได้กับ Amazon S3 API ทำให้คุณสามารถใช้เครื่องมือและไลบรารี ที่มีอยู่แล้วได้ทันที โดยมีคุณสมบัติหลักดังนี้:
- S3-Compatible: ใช้ AWS SDK ที่มีอยู่ได้ทันที ไม่ต้องเรียนรู้ใหม่
- CDN ในตัว: เร่งความเร็วการโหลดไฟล์ทั่วโลกอัตโนมัติ
- Scalable: จัดเก็บข้อมูลได้ไม่จำกัด ไม่ต้องกังวลเรื่อง capacity
- ราคาประหยัด: เริ่มต้น $5/เดือน สำหรับ 250GB storage
- High Availability: ข้อมูลถูก replicate อัตโนมัติ
- SSL/TLS: เข้ารหัสการเชื่อมต่ออัตโนมัติ
Use Cases ยอดนิยม
Static Assets
เก็บรูปภาพ, CSS, JavaScript สำหรับเว็บไซต์
Media Files
เก็บวิดีโอ, ไฟล์เสียง, เอกสาร PDF
Backup & Archive
สำรองข้อมูล database, log files
Mobile Apps
เก็บไฟล์ที่ผู้ใช้อัปโหลดจากแอป
User Uploads
Profile pictures, avatars, documents
CI/CD Artifacts
เก็บ build artifacts, deployment files
Architecture Overview
Architecture แสดงการเชื่อมต่อจาก Application ไปยัง DigitalOcean Spaces ผ่าน S3 API
สิ่งที่ต้องเตรียม
DigitalOcean Account
- • สร้าง account ที่ digitalocean.com
- • เติมเงินขั้นต่ำ $5
- • ใช้งานได้ทันทีหลัง verify
API Keys (Access Key + Secret)
- • ไปที่ API → Spaces Keys
- • กด Generate New Key
- • เก็บ Key และ Secret ไว้ให้ปลอดภัย
Space (Bucket)
- • ไปที่ Spaces → Create Space
- • เลือก Region (แนะนำ Singapore สำหรับไทย)
- • ตั้งชื่อ bucket ที่ unique
Development Environment
- • Node.js 18+ หรือ Python 3.8+
- • npm หรือ pip
- • Code editor (VS Code แนะนำ)
สร้าง Space และ API Keys
สร้าง Space (Bucket)
- 1 เข้าสู่ DigitalOcean Control Panel
- 2 ไปที่เมนู Spaces → Create Space
- 3 เลือก Region: Singapore (sgp1) - ใกล้ไทยที่สุด
-
4
ตั้งชื่อ Space: เช่น
my-app-assets - 5 เลือก Restrict File Listing เพื่อความปลอดภัย
- 6 กด Create Space
สร้าง API Keys
- 1 ไปที่ API → Spaces Keys
- 2 กด Generate New Key
-
3
ตั้งชื่อ Key: เช่น
my-app-key - 4 คัดลอก Access Key และ Secret Key เก็บไว้
สำคัญ: Secret Key จะแสดงเฉพาะครั้งเดียว หากลืมต้องสร้าง Key ใหม่
ตั้งค่า Environment Variables
สร้างไฟล์ .env เพื่อเก็บ credentials:
# DigitalOcean Spaces Credentials
DO_SPACES_KEY=your_access_key_here
DO_SPACES_SECRET=your_secret_key_here
DO_SPACES_BUCKET=my-app-assets
DO_SPACES_REGION=sgp1
DO_SPACES_ENDPOINT=https://sgp1.digitaloceanspaces.com
Node.js Integration
ติดตั้ง Dependencies
# สร้างโปรเจคใหม่
mkdir digitalocean-spaces-demo
cd digitalocean-spaces-demo
npm init -y
# ติดตั้ง AWS SDK v3 (S3 client)
npm install @aws-sdk/client-s3
# ติดตั้ง dotenv สำหรับ environment variables
npm install dotenv
# ติดตั้ง multer สำหรับ file upload (optional)
npm install multer
สร้าง S3 Client
import { S3Client } from '@aws-sdk/client-s3';
import dotenv from 'dotenv';
dotenv.config();
const s3Client = new S3Client({
forcePathStyle: false, // ใช้ subdomain/virtual calling
region: 'us-east-1', // AWS region (ต้องใช้ us-east-1)
endpoint: process.env.DO_SPACES_ENDPOINT,
credentials: {
accessKeyId: process.env.DO_SPACES_KEY,
secretAccessKey: process.env.DO_SPACES_SECRET
}
});
export default s3Client;
หมายเหตุ: ต้องใช้ region: 'us-east-1' เพราะเป็น requirement ของ AWS SDK
แต่ endpoint จะชี้ไป DigitalOcean จริง
อัปโหลดไฟล์
import { PutObjectCommand } from '@aws-sdk/client-s3';
import fs from 'fs';
import s3Client from './spaces-client.js';
async function uploadFile(localPath, remoteKey) {
const fileContent = fs.readFileSync(localPath);
const params = {
Bucket: process.env.DO_SPACES_BUCKET,
Key: remoteKey, // เช่น 'images/profile.jpg'
Body: fileContent,
ACL: 'public-read', // หรือ 'private'
ContentType: 'image/jpeg' // MIME type
};
try {
const data = await s3Client.send(new PutObjectCommand(params));
console.log('✅ Upload successful!');
console.log('File URL:', `https://${process.env.DO_SPACES_BUCKET}.sgp1.digitaloceanspaces.com/${remoteKey}`);
return data;
} catch (err) {
console.error('❌ Upload error:', err);
throw err;
}
}
// ตัวอย่างการใช้งาน
uploadFile('./local-image.jpg', 'uploads/profile-2024.jpg');
ดาวน์โหลดไฟล์
import { GetObjectCommand } from '@aws-sdk/client-s3';
import fs from 'fs';
import s3Client from './spaces-client.js';
async function downloadFile(remoteKey, localPath) {
const params = {
Bucket: process.env.DO_SPACES_BUCKET,
Key: remoteKey
};
try {
const data = await s3Client.send(new GetObjectCommand(params));
// แปลง stream เป็น buffer
const chunks = [];
for await (const chunk of data.Body) {
chunks.push(chunk);
}
const buffer = Buffer.concat(chunks);
// บันทึกไฟล์
fs.writeFileSync(localPath, buffer);
console.log(`✅ Downloaded: ${remoteKey} → ${localPath}`);
} catch (err) {
console.error('❌ Download error:', err);
throw err;
}
}
// ตัวอย่างการใช้งาน
downloadFile('uploads/profile-2024.jpg', './downloaded-image.jpg');
แสดงรายการไฟล์
import { ListObjectsV2Command } from '@aws-sdk/client-s3';
import s3Client from './spaces-client.js';
async function listFiles(prefix = '') {
const params = {
Bucket: process.env.DO_SPACES_BUCKET,
Prefix: prefix, // เช่น 'images/' เพื่อกรองเฉพาะโฟลเดอร์
MaxKeys: 100
};
try {
const data = await s3Client.send(new ListObjectsV2Command(params));
console.log(`📁 Files in bucket (${data.KeyCount} items):`);
data.Contents?.forEach(item => {
const size = (item.Size / 1024).toFixed(2);
console.log(` - ${item.Key} (${size} KB)`);
});
return data.Contents;
} catch (err) {
console.error('❌ List error:', err);
throw err;
}
}
// ตัวอย่างการใช้งาน
listFiles('uploads/'); // แสดงไฟล์ในโฟลเดอร์ uploads
ลบไฟล์
import { DeleteObjectCommand } from '@aws-sdk/client-s3';
import s3Client from './spaces-client.js';
async function deleteFile(remoteKey) {
const params = {
Bucket: process.env.DO_SPACES_BUCKET,
Key: remoteKey
};
try {
await s3Client.send(new DeleteObjectCommand(params));
console.log(`🗑️ Deleted: ${remoteKey}`);
} catch (err) {
console.error('❌ Delete error:', err);
throw err;
}
}
// ตัวอย่างการใช้งาน
deleteFile('uploads/old-file.jpg');
Python Integration
ติดตั้ง Dependencies
# ติดตั้ง boto3 (AWS SDK for Python)
pip install boto3 python-dotenv
สร้าง S3 Client
import os
import boto3
from botocore.client import Config
from dotenv import load_dotenv
load_dotenv()
# สร้าง S3 client สำหรับ DigitalOcean Spaces
session = boto3.session.Session()
s3_client = session.client(
's3',
region_name=os.getenv('DO_SPACES_REGION'),
endpoint_url=os.getenv('DO_SPACES_ENDPOINT'),
aws_access_key_id=os.getenv('DO_SPACES_KEY'),
aws_secret_access_key=os.getenv('DO_SPACES_SECRET'),
config=Config(s3={'addressing_style': 'virtual'})
)
BUCKET_NAME = os.getenv('DO_SPACES_BUCKET')
อัปโหลดไฟล์
import os
from spaces_client import s3_client, BUCKET_NAME
def upload_file(local_path, remote_key, public=True):
"""
อัปโหลดไฟล์ไปยัง DigitalOcean Spaces
Args:
local_path: พาธไฟล์ในเครื่อง
remote_key: ชื่อไฟล์บน Spaces (เช่น 'images/profile.jpg')
public: True สำหรับ public-read, False สำหรับ private
"""
extra_args = {
'ContentType': 'image/jpeg' # ปรับตามประเภทไฟล์
}
if public:
extra_args['ACL'] = 'public-read'
try:
s3_client.upload_file(
local_path,
BUCKET_NAME,
remote_key,
ExtraArgs=extra_args
)
url = f"https://{BUCKET_NAME}.sgp1.digitaloceanspaces.com/{remote_key}"
print(f"✅ Upload successful! URL: {url}")
return url
except Exception as e:
print(f"❌ Upload error: {e}")
raise
# ตัวอย่างการใช้งาน
if __name__ == "__main__":
upload_file("./local-image.jpg", "uploads/profile.jpg")
ดาวน์โหลดไฟล์
from spaces_client import s3_client, BUCKET_NAME
def download_file(remote_key, local_path):
"""ดาวน์โหลดไฟล์จาก DigitalOcean Spaces"""
try:
s3_client.download_file(
BUCKET_NAME,
remote_key,
local_path
)
print(f"✅ Downloaded: {remote_key} → {local_path}")
except Exception as e:
print(f"❌ Download error: {e}")
raise
# ตัวอย่างการใช้งาน
download_file("uploads/profile.jpg", "./downloaded.jpg")
แสดงรายการไฟล์
from spaces_client import s3_client, BUCKET_NAME
def list_files(prefix=''):
"""แสดงรายการไฟล์ใน bucket"""
try:
response = s3_client.list_objects_v2(
Bucket=BUCKET_NAME,
Prefix=prefix
)
print(f"📁 Files in bucket ({response['KeyCount']} items):")
for obj in response.get('Contents', []):
size_kb = obj['Size'] / 1024
print(f" - {obj['Key']} ({size_kb:.2f} KB)")
return response.get('Contents', [])
except Exception as e:
print(f"❌ List error: {e}")
raise
# ตัวอย่างการใช้งาน
list_files("uploads/")
สร้าง Presigned URL
from spaces_client import s3_client, BUCKET_NAME
def generate_presigned_url(remote_key, expiration=3600):
"""
สร้าง URL ชั่วคราวสำหรับดาวน์โหลดไฟล์ private
Args:
remote_key: ชื่อไฟล์บน Spaces
expiration: เวลาหมดอายุเป็นวินาที (default: 1 ชั่วโมง)
"""
try:
url = s3_client.generate_presigned_url(
'get_object',
Params={
'Bucket': BUCKET_NAME,
'Key': remote_key
},
ExpiresIn=expiration
)
print(f"🔗 Presigned URL (valid for {expiration}s):")
print(url)
return url
except Exception as e:
print(f"❌ Error: {e}")
raise
# ตัวอย่างการใช้งาน
generate_presigned_url("private/secret.pdf", expiration=300) # 5 นาที
Use Case: Presigned URL เหมาะสำหรับแชร์ไฟล์ private ชั่วคราว เช่น ให้ผู้ใช้ดาวน์โหลดใบเสร็จ PDF ที่หมดอายุใน 10 นาที
CDN Configuration
DigitalOcean Spaces มี Built-in CDN ที่ช่วยเร่งความเร็วในการโหลดไฟล์ จากทั่วโลก โดยอัตโนมัติ
ความเร็วสูง
- • Edge locations ทั่วโลก
- • ลด latency สำหรับผู้ใช้ในไทย
- • Cache อัตโนมัติ
ความปลอดภัย
- • SSL/TLS อัตโนมัติ
- • DDoS protection
- • Custom domain support
ตั้งค่า Custom Domain + CDN
- 1 ไปที่ Spaces → Settings → CDN
-
2
เพิ่ม Custom Domain:
cdn.yourdomain.com - 3 เพิ่ม CNAME record ใน DNS:
Type: CNAME
Name: cdn
Value: my-bucket.sgp1.cdn.digitaloceanspaces.com
TTL: 3600
ตัวอย่าง URL
Default CDN URL:
https://my-bucket.sgp1.cdn.digitaloceanspaces.com/images/photo.jpg
Custom Domain:
https://cdn.yourdomain.com/images/photo.jpg
Express.js + Multer Integration
ตัวอย่างการสร้าง API สำหรับอัปโหลดไฟล์ไปยัง DigitalOcean Spaces ด้วย Express.js และ Multer
import express from 'express';
import multer from 'multer';
import { S3Client } from '@aws-sdk/client-s3';
import multerS3 from 'multer-s3';
import dotenv from 'dotenv';
dotenv.config();
const app = express();
// สร้าง S3 Client
const s3 = new S3Client({
region: 'us-east-1',
endpoint: process.env.DO_SPACES_ENDPOINT,
credentials: {
accessKeyId: process.env.DO_SPACES_KEY,
secretAccessKey: process.env.DO_SPACES_SECRET
}
});
// กำหนดค่า Multer สำหรับอัปโหลดไปยัง Spaces
const upload = multer({
storage: multerS3({
s3: s3,
bucket: process.env.DO_SPACES_BUCKET,
acl: 'public-read',
key: function (req, file, cb) {
const fileName = `uploads/${Date.now()}-${file.originalname}`;
cb(null, fileName);
},
contentType: function (req, file, cb) {
cb(null, file.mimetype);
}
}),
limits: {
fileSize: 5 * 1024 * 1024 // 5MB max
}
});
// API สำหรับอัปโหลดไฟล์เดียว
app.post('/upload', upload.single('file'), (req, res) => {
if (!req.file) {
return res.status(400).json({ error: 'No file uploaded' });
}
res.json({
message: '✅ Upload successful!',
url: req.file.location,
key: req.file.key
});
});
// API สำหรับอัปโหลดหลายไฟล์ (สูงสุด 10 ไฟล์)
app.post('/upload-multiple', upload.array('files', 10), (req, res) => {
const files = req.files.map(file => ({
url: file.location,
key: file.key
}));
res.json({
message: `✅ Uploaded ${files.length} files!`,
files: files
});
});
// เริ่ม server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`🚀 Server running on port ${PORT}`);
});
ทดสอบด้วย curl
# อัปโหลดไฟล์เดียว
curl -X POST -F "file=@./photo.jpg" http://localhost:3000/upload
# อัปโหลดหลายไฟล์
curl -X POST -F "files=@./photo1.jpg" -F "files=@./photo2.jpg" http://localhost:3000/upload-multiple
Pricing (2025)
| Plan | Storage | Bandwidth | Price |
|---|---|---|---|
| Basic | 250 GB | 1 TB | $5/month |
| Professional | 1 TB | 4 TB | $20/month |
| Business | 10 TB | 40 TB | $180/month |
| Overage | $0.02/GB | $0.01/GB | Extra usage |
เปรียบเทียบกับ AWS S3: DigitalOcean Spaces มีราคาถูกกว่าประมาณ 40-50% และรวม CDN ในตัวแล้ว ไม่ต้องจ่ายเพิ่ม
Use Cases ในประเทศไทย
E-commerce
เก็บรูปสินค้า รูปหมวดหมู่ และไฟล์ PDF สำหรับคู่มือสินค้า
- • รูปสินค้าหลายขนาด (thumbnail, medium, large)
- • ไฟล์ PDF ใบเสร็จ/ใบกำกับภาษี
- • วิดีโอสาธิตสินค้า
Media Streaming
เก็บวิดีโอออนไลน์คอร์ส พอดแคสต์ และไฟล์เสียง
- • วิดีโอคอร์สเรียนออนไลน์
- • ไฟล์เสียงพอดแคสต์
- • ไฟล์ subtitle หลายภาษา
Government/Enterprise
เก็บเอกสารราชการ แบบฟอร์ม PDF และไฟล์ข้อมูล
- • เอกสาร PDF ดาวน์โหลด
- • แบบฟอร์มต่างๆ
- • ไฟล์ข้อมูล CSV/Excel
Mobile Apps
เก็บไฟล์ที่ผู้ใช้อัปโหลดจากแอปมือถือ
- • รูปโปรไฟล์ผู้ใช้
- • รูปสลิปโอนเงิน
- • เอกสารแนบต่างๆ
แนะนำ: เลือก Region Singapore (sgp1) สำหรับผู้ใช้ในประเทศไทย เพราะ latency ต่ำที่สุด (ประมาณ 20-30ms)
Troubleshooting
Error: "Access Denied"
สาเหตุ: API Key หรือ Secret ไม่ถูกต้อง
แก้ไข: ตรวจสอบว่า DO_SPACES_KEY และ DO_SPACES_SECRET ตรงกับที่สร้างไว้ และไม่มีช่องว่าง extra spaces
Error: "Bucket Already Exists"
สาเหตุ: ชื่อ bucket ซ้ำกับ bucket อื่น
แก้ไข: ใช้ชื่อ bucket ที่ unique มากขึ้น เช่น mycompany-app-prod-2024
Error: "Network Timeout"
สาเหตุ: ไฟล์ใหญ่เกินไป หรือ network ช้า
แก้ไข: ใช้ multipart upload สำหรับไฟล์ใหญ่กว่า 100MB หรือเพิ่ม timeout ใน configuration
Error: "Invalid Endpoint"
สาเหตุ: Endpoint URL ไม่ถูกต้อง
แก้ไข: ตรวจสอบว่า endpoint เป็น https://sgp1.digitaloceanspaces.com
(ต้องมี https://)
สรุป
ข้อดีของ DigitalOcean Spaces
- S3-Compatible - ใช้ AWS SDK ที่มีอยู่ได้ทันที
- รวม CDN ในตัว - เร่งความเร็วได้ทั่วโลก
- ราคาประหยัด - เริ่ม $5/เดือน
- Region Singapore - latency ต่ำในไทย
เหมาะสำหรับ
- Startups และ SME ในไทย
- เว็บไซต์ที่มี static assets มาก
- Mobile apps ที่ต้องการ file storage
- DevOps ที่ต้องการ backup storage
อ่านเพิ่มเติมที่ DigitalOcean Spaces Documentation