- Tính năng chính
- Thông tin phiên bản
- Yêu cầu hệ thống
- Cài đặt và cấu hình
- Cách sử dụng với API Key tĩnh
- Upload một file
- Upload nhiều file cùng lúc
- Ví dụ với PHP và cURL
- Cách sử dụng với HMAC Signature
- Image Optimizer và WebP Conversion
- Cấu trúc Response
- Cloudflare R2 và BunnyCDN
- Cloudflare R2
- BunnyCDN Storage
- Tích hợp với WordPress
- Tích hợp với JavaScript
- Bảo mật và tối ưu
- Xử lý lỗi thường gặp
- Mở rộng và tùy biến
Tính năng chính
Init Uploader cung cấp đầy đủ các tính năng cần thiết cho một hệ thống upload ảnh chuyên nghiệp:
- Upload linh hoạt: Hỗ trợ cả upload từng file đơn lẻ và bulk upload nhiều file cùng lúc, giúp tối ưu thời gian khi cần upload hàng loạt ảnh.
- Quản lý thư mục: Tổ chức ảnh theo cấu trúc path tùy chỉnh, ví dụ:
manga-123/chapter-5/page-01.jpg, giúp dễ dàng quản lý và phân loại. - Thông tin chi tiết: Tự động trả về URL đầy đủ, chiều rộng, chiều cao, kích thước file và đường dẫn lưu trữ của mỗi ảnh sau khi upload thành công.
- Bảo mật cao: Hỗ trợ hai phương thức xác thực – API Key tĩnh cho đơn giản hoặc HMAC signature với timestamp để chống replay attack.
- HTTPS bắt buộc: Tùy chọn yêu cầu kết nối HTTPS để bảo vệ dữ liệu trong quá trình truyền tải.
- Validate chặt chẽ: Kiểm tra định dạng file, kích thước, extension và MIME type để đảm bảo chỉ nhận ảnh hợp lệ.
- Xử lý thông minh: Tự động tạo thư mục, đổi tên file trùng lặp, và ghi log chi tiết để dễ dàng debug.
- Image Optimizer: Tích hợp sẵn hệ thống resize và tối ưu ảnh tự động sau khi upload, hỗ trợ JPEG, PNG và WebP.
- WebP Conversion: Tự động convert JPEG và PNG sang WebP để giảm dung lượng ảnh và tăng tốc độ tải trang. GIF được tự động bỏ qua để giữ nguyên animation.
- Cloudflare R2: Hỗ trợ upload trực tiếp lên Cloudflare R2 bằng AWS Signature V4 thuần PHP + cURL, không cần cài AWS SDK.
- BunnyCDN Storage: Hỗ trợ upload trực tiếp lên BunnyCDN Storage Zone với HTTP API và regional endpoint.
- CDN Fallback: Nếu upload CDN thất bại, hệ thống sẽ tự động fallback về local storage để tránh gián đoạn hoạt động.
- Tự động dọn local: Tùy chọn tự động xóa file local sau khi upload CDN thành công để tiết kiệm dung lượng server.
Thông tin phiên bản
- Phiên bản: 1.2.0
- Cập nhật: 2026-05-27
Yêu cầu hệ thống
Để triển khai Init Uploader, server của bạn cần đáp ứng các yêu cầu tối thiểu sau:
- PHP: Phiên bản 7.4 trở lên, khuyến nghị sử dụng PHP 8.0 hoặc cao hơn để có hiệu năng tốt nhất.
- Extensions: Cần cài đặt extension gd hoặc imagick để lấy thông tin kích thước ảnh, và fileinfo để validate MIME type.
- Quyền truy cập: Thư mục uploads cần có quyền ghi (chmod 755 hoặc 775) để server có thể lưu file.
- HTTPS: Nếu bật tính năng REQUIRE_HTTPS, cần có SSL certificate hợp lệ được cấu hình trên server.
- Domain/Subdomain: Một domain hoặc subdomain đã trỏ về server để truy cập ảnh sau khi upload.
Cài đặt và cấu hình
Sau khi tải về file init-uploader.php, mở file và điều chỉnh các thông số trong phần CONFIGURATION ở đầu file:
define('API_KEY', 'your-secret-api-key-here-change-this');
define('SECRET_KEY', 'your-secret-hmac-key-change-this');
define('USE_HMAC_AUTH', true);
define('UPLOAD_DIR', __DIR__ . '/uploads');
define('BASE_URL', 'https://your-domain.com');
define('MAX_FILE_SIZE', 10 * 1024 * 1024);
define('REQUIRE_HTTPS', true);
define('OPTIMIZER_ENABLED', true);
define('OPTIMIZER_MAX_WIDTH', 900);
define('OPTIMIZER_JPEG_QUALITY', 80);
define('OPTIMIZER_PNG_LEVEL', 6);
define('OPTIMIZER_CONVERT_TO_WEBP', true);
define('OPTIMIZER_WEBP_QUALITY', 82);
define('R2_ENABLED', false);
define('R2_ACCOUNT_ID', 'your-account-id');
define('R2_ACCESS_KEY_ID', 'your-r2-access-key-id');
define('R2_SECRET_ACCESS_KEY', 'your-r2-secret-access-key');
define('R2_BUCKET', 'your-bucket-name');
define('R2_PUBLIC_URL', 'https://your-public-url.com');
define('BUNNY_ENABLED', false);
define('BUNNY_STORAGE_ZONE', 'your-storage-zone');
define('BUNNY_API_KEY', 'your-bunny-api-key');
define('BUNNY_STORAGE_REGION', 'storage.bunnycdn.com');
define('BUNNY_PUBLIC_URL', 'https://your-zone.b-cdn.net');
Các thông số quan trọng cần thay đổi:
- API_KEY: Khóa bí mật cho phương thức xác thực đơn giản, nên sử dụng chuỗi ngẫu nhiên dài ít nhất 32 ký tự.
- SECRET_KEY: Khóa bí mật cho HMAC signature, tương tự API_KEY nhưng chỉ dùng khi bật USE_HMAC_AUTH.
- USE_HMAC_AUTH: Đặt true để dùng HMAC signature (bảo mật cao), false để dùng API key tĩnh (đơn giản hơn).
- BASE_URL: URL gốc của domain, ví dụ: https://cdn.example.com hoặc https://example.com/cdn.
- MAX_FILE_SIZE: Kích thước file tối đa cho phép tính bằng bytes, mặc định 10MB.
Upload file init-uploader.php lên server, đảm bảo thư mục uploads có quyền ghi, và bạn đã sẵn sàng sử dụng.
Cách sử dụng với API Key tĩnh
Phương thức đơn giản nhất là sử dụng API Key tĩnh. Đặt USE_HMAC_AUTH thành false trong config, sau đó gửi request với header X-API-Key:
Upload một file
curl -X POST https://your-domain.com/init-uploader.php \
-H "X-API-Key: your-secret-api-key" \
-F "file=@/path/to/image.jpg" \
-F "path=manga-123/chapter-1"
Upload nhiều file cùng lúc
curl -X POST https://your-domain.com/init-uploader.php \
-H "X-API-Key: your-secret-api-key" \
-F "files[]=@/path/to/image1.jpg" \
-F "files[]=@/path/to/image2.jpg" \
-F "files[]=@/path/to/image3.jpg" \
-F "path=manga-123/chapter-1"
Ví dụ với PHP và cURL
<?php
$ch = curl_init('https://your-domain.com/init-uploader.php');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-API-Key: your-secret-api-key'
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
'file' => new CURLFile('/path/to/image.jpg'),
'path' => 'manga-123/chapter-1'
]);
$response = curl_exec($ch);
$result = json_decode($response, true);
if ($result['success']) {
foreach ($result['data']['files'] as $file) {
echo "URL: " . $file['url'] . "\n";
echo "Width: " . $file['width'] . "px\n";
echo "Height: " . $file['height'] . "px\n";
}
}
curl_close($ch);
?>
Cách sử dụng với HMAC Signature
HMAC signature mang lại mức độ bảo mật cao hơn bằng cách kết hợp timestamp với khóa bí mật. Mỗi request chỉ có giá trị trong khoảng thời gian nhất định, giúp chống lại các cuộc tấn công replay.
Đặt USE_HMAC_AUTH thành true trong config, sau đó tạo signature như sau:
<?php
$timestamp = time();
$signature = hash_hmac('sha256', (string)$timestamp, 'your-secret-hmac-key');
$ch = curl_init('https://your-domain.com/init-uploader.php');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-Timestamp: ' . $timestamp,
'X-Signature: ' . $signature
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
'file' => new CURLFile('/path/to/image.jpg'),
'path' => 'manga-123/chapter-1'
]);
$response = curl_exec($ch);
$result = json_decode($response, true);
curl_close($ch);
?>
Lưu ý rằng timestamp phải là Unix timestamp hiện tại. Server sẽ kiểm tra và chỉ chấp nhận request có timestamp chênh lệch không quá 5 phút so với thời gian server.
Image Optimizer và WebP Conversion
Init Uploader tích hợp sẵn hệ thống tối ưu ảnh tự động ngay sau khi upload hoàn tất. Điều này giúp giảm đáng kể dung lượng ảnh mà không cần sử dụng thêm service bên ngoài.
Khi bật:
define('OPTIMIZER_ENABLED', true);
Hệ thống sẽ:
- Tự động resize ảnh nếu vượt quá
OPTIMIZER_MAX_WIDTH. - Nén JPEG và WebP bằng quality tùy chỉnh.
- Nén PNG lossless.
- Giữ nguyên alpha transparency cho PNG và WebP.
Nếu muốn tự động convert JPEG và PNG sang WebP:
define('OPTIMIZER_CONVERT_TO_WEBP', true);
define('OPTIMIZER_WEBP_QUALITY', 82);
Khi bật WebP conversion:
- Chỉ JPEG và PNG được convert sang WebP.
- GIF được tự động bỏ qua hoàn toàn để giữ animation.
- File output sẽ đổi extension thành
.webp. - Nếu
imagewebp()thất bại, hệ thống sẽ fallback về optimize thông thường thay vì crash.
Lưu ý rằng:
OPTIMIZER_ENABLEDphải được bật thì WebP conversion mới hoạt động.- Server cần cài extension GD có hỗ trợ WebP.
Cấu trúc Response
Init Uploader luôn trả về JSON response với cấu trúc nhất quán. Khi upload thành công:
{
"success": true,
"data": {
"uploaded": 2,
"failed": 0,
"files": [
{
"success": true,
"url": "https://your-domain.com/uploads/manga-123/chapter-1/image1.jpg",
"width": 1920,
"height": 1080,
"filename": "image1.jpg",
"path": "manga-123/chapter-1",
"size": 245678
},
{
"success": true,
"url": "https://your-domain.com/uploads/manga-123/chapter-1/image2.jpg",
"width": 1280,
"height": 720,
"filename": "image2.jpg",
"path": "manga-123/chapter-1",
"size": 189234
}
]
},
"timestamp": 1705132800
}
Khi có lỗi xảy ra:
{
"success": false,
"data": null,
"error": "Invalid API key",
"timestamp": 1705132800
}
Nếu upload một số file thành công và một số thất bại, response sẽ bao gồm cả hai thông tin:
{
"success": true,
"data": {
"uploaded": 1,
"failed": 1,
"files": [
{
"success": true,
"url": "https://your-domain.com/uploads/test/valid.jpg",
"width": 800,
"height": 600,
"filename": "valid.jpg",
"path": "test",
"size": 102400
}
],
"errors": [
"invalid.txt: Invalid file extension. Allowed: jpg, jpeg, png, gif, webp"
]
},
"timestamp": 1705132800
}
Cloudflare R2 và BunnyCDN
Init Uploader hỗ trợ upload trực tiếp lên Cloudflare R2 hoặc BunnyCDN Storage Zone mà không cần cài thêm SDK ngoài.
Cloudflare R2
Để bật Cloudflare R2:
define('R2_ENABLED', true);
define('R2_ACCOUNT_ID', 'your-account-id');
define('R2_ACCESS_KEY_ID', 'your-r2-access-key-id');
define('R2_SECRET_ACCESS_KEY', 'your-r2-secret-access-key');
define('R2_BUCKET', 'your-bucket-name');
define('R2_PUBLIC_URL', 'https://cdn.example.com');
define('R2_DELETE_LOCAL', false);
Init Uploader sử dụng AWS Signature Version 4 thuần PHP + cURL để upload lên R2, hoàn toàn không cần AWS SDK.
Sau khi upload thành công:
- URL trả về sẽ là URL của R2/CDN.
- Có thể dùng custom domain hoặc
.r2.dev. - Nếu bật
R2_DELETE_LOCAL, file local sẽ tự động bị xóa.
BunnyCDN Storage
Để bật BunnyCDN:
define('BUNNY_ENABLED', true);
define('BUNNY_STORAGE_ZONE', 'your-storage-zone');
define('BUNNY_API_KEY', 'your-api-key');
define('BUNNY_STORAGE_REGION', 'ny.storage.bunnycdn.com');
define('BUNNY_PUBLIC_URL', 'https://cdn.example.com');
define('BUNNY_DELETE_LOCAL', false);
Tính năng hỗ trợ:
- BunnyCDN Storage HTTP API.
- Regional endpoint như New York, Singapore, Frankfurt…
- Custom Pull Zone domain.
- Tự động fallback về local storage nếu CDN upload thất bại.
Lưu ý:
- Cloudflare R2 được ưu tiên trước BunnyCDN nếu cả hai cùng bật.
- Upload CDN chỉ diễn ra sau khi optimizer hoàn tất xử lý ảnh.
- Server cần bật extension cURL.
Tích hợp với WordPress
Để sử dụng Init Uploader trong WordPress theme hoặc plugin, bạn có thể tạo một helper function:
function init_uploader_upload($file_path, $remote_path = '') {
$api_key = 'your-secret-api-key';
$endpoint = 'https://your-domain.com/init-uploader.php';
$ch = curl_init($endpoint);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-API-Key: ' . $api_key
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
'file' => new CURLFile($file_path),
'path' => $remote_path
]);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($http_code !== 200) {
return false;
}
$result = json_decode($response, true);
if (!$result['success']) {
return false;
}
return $result['data']['files'][0];
}
// Sử dụng
$uploaded = init_uploader_upload('/tmp/photo.jpg', 'gallery/2024');
if ($uploaded) {
echo 'URL: ' . $uploaded['url'];
echo 'Size: ' . $uploaded['width'] . 'x' . $uploaded['height'];
}
Tích hợp với JavaScript
Upload ảnh từ trình duyệt với JavaScript và Fetch API:
async function uploadImage(file, path = '') {
const formData = new FormData();
formData.append('file', file);
formData.append('path', path);
const response = await fetch('https://your-domain.com/init-uploader.php', {
method: 'POST',
headers: {
'X-API-Key': 'your-secret-api-key'
},
body: formData
});
const result = await response.json();
if (result.success) {
return result.data.files[0];
} else {
throw new Error(result.error);
}
}
// Sử dụng với input file
document.getElementById('fileInput').addEventListener('change', async (e) => {
const file = e.target.files[0];
try {
const uploaded = await uploadImage(file, 'uploads/2024');
console.log('Uploaded:', uploaded.url);
console.log('Dimensions:', uploaded.width + 'x' + uploaded.height);
} catch (error) {
console.error('Upload failed:', error.message);
}
});
Bảo mật và tối ưu
Để đảm bảo hệ thống vận hành an toàn và hiệu quả, cần lưu ý một số điểm sau:
- Bảo vệ API Key: Không bao giờ commit API key hoặc SECRET key vào git repository. Sử dụng biến môi trường hoặc file config riêng được exclude khỏi version control.
- Giới hạn quyền truy cập: Cấu hình firewall hoặc .htaccess để chỉ cho phép IP tin cậy truy cập vào
init-uploader.phpnếu chỉ dùng nội bộ. - Cấu hình Nginx/Apache: Đảm bảo thư mục uploads có thể truy cập qua HTTP/HTTPS để hiển thị ảnh, nhưng file .php trong đó không được thực thi.
- Rate limiting: Sử dụng fail2ban hoặc các công cụ tương tự để chống brute force API key.
- Backup định kỳ: Thiết lập cron job để backup thư mục uploads và database nếu bạn lưu metadata.
- CDN: Nếu lượng truy cập cao, cân nhắc đặt CloudFlare hoặc CDN khác phía trước server để cache ảnh tĩnh.
- Monitoring: Theo dõi file upload.log để phát hiện các hành vi bất thường hoặc lỗi hệ thống.
Xử lý lỗi thường gặp
Một số lỗi phổ biến và cách khắc phục:
- 403 HTTPS required: Server không chạy HTTPS hoặc request đi qua HTTP. Cài đặt SSL certificate hoặc tắt REQUIRE_HTTPS trong config.
- 401 Invalid API key: API key không đúng hoặc header không được gửi đúng cách. Kiểm tra lại X-API-Key trong request.
- 401 Request timestamp expired: Timestamp chênh lệch quá 5 phút so với server time. Đồng bộ thời gian hoặc tăng HMAC_TIME_WINDOW.
- 500 Failed to create upload directory: Server không có quyền ghi. Chạy chmod 755 hoặc 775 cho thư mục uploads.
- 400 File size exceeds maximum: File vượt quá giới hạn MAX_FILE_SIZE. Giảm kích thước ảnh hoặc tăng giới hạn trong config.
- 400 Invalid file extension: File không phải định dạng cho phép. Chỉ chấp nhận jpg, jpeg, png, gif, webp.
Mở rộng và tùy biến
Init Uploader được thiết kế dễ dàng tùy biến theo nhu cầu cụ thể:
- Thêm watermark: Sử dụng thư viện GD hoặc Imagick để tự động chèn watermark lên ảnh trước khi lưu.
- Resize tự động: Tạo nhiều version với kích thước khác nhau (thumbnail, medium, large) ngay sau khi upload.
- Tối ưu ảnh: Tích hợp công cụ như jpegoptim, optipng để giảm dung lượng mà không mất chất lượng.
- Lưu metadata: Ghi thông tin ảnh vào database MySQL hoặc SQLite để dễ dàng tìm kiếm và quản lý.
- Webhook: Gửi notification tới Slack, Discord hoặc endpoint khác sau khi upload thành công.
- Xóa ảnh tự động: Thêm endpoint DELETE để xóa ảnh qua API thay vì phải SSH vào server.
Init Uploader hoàn toàn miễn phí cho mọi mục đích sử dụng. Nếu module này hữu ích với bạn, hãy chia sẻ với cộng đồng và để lại đánh giá để giúp dự án phát triển hơn nữa.
Bình luận