Lưu trữ file trên Amazon S3 thay vì trên server truyền thống mang lại nhiều lợi ích vượt trội. S3 cung cấp khả năng mở rộng không giới hạn, đảm bảo hiệu suất và tốc độ tải trang luôn ổn định ngay cả khi lượng truy cập tăng cao. Đặc biệt, S3 đảm bảo độ tin cậy và bảo mật cao, giúp dữ liệu của bạn luôn an toàn và dễ dàng quản lý. Hơn nữa, việc tích hợp dễ dàng với các dịch vụ khác của AWS giúp bạn tối ưu hóa hệ thống một cách linh hoạt và hiệu quả.
Dù có nhiều plugin đã hỗ trợ việc này, nhưng phí sử dụng cao và plugin thường đi kèm với nhiều tính năng không cần thiết. Việc tự code sẽ hiệu quả hơn, dễ kiểm soát hơn và giúp tiết kiệm chi phí.
Dưới đây là các bước để làm điều này
Bước 1 : Chuẩn bị môi trường
Tạo bucket trên S3 và lấy những thông tin sau dán vào wp-config.php theo hình bên dưới
Install thư viện SDK của S3 bằng lệnh bên dưới
composer require aws/aws-sdk-php
Bước 2 : Viết code
Viết hàm để upload lên s3
function upload_to_s3($file_path) {
try {
// chuẩn bị config s3
$bucket = S3_UPLOADS_BUCKET;
$s3 = new Aws\S3\S3Client([
'version' => 'latest',
'region' => S3_UPLOADS_REGION,
'credentials' => [
'key' => S3_UPLOADS_KEY,
'secret' => S3_UPLOADS_SECRET,
]
]);
// sửa lại đường dẫn
$file_url = str_replace(UPLOAD_DIR, UPLOAD_URI, $file_path);
$file_name = str_replace(home_url('/'), '', $file_url);
// Thực hiện upload file lên S3
$result = $s3->putObject([
'Bucket' => $bucket,
'Key' => $file_name,
'Body' => fopen($file_path, 'r'),
'ACL' => 'public-read'
]);
return true;
} catch (Aws\Exception\S3Exception $e) {
// Xử lý ngoại lệ S3Exception
error_log("Error uploading file to S3: " . $e->getMessage());
return false;
} catch (Exception $e) {
// Xử lý ngoại lệ khác
error_log("An unexpected error occurred: " . $e->getMessage());
return false;
}
}
Sử dụng hook của wordpress để upload lên S3
add_filter('wp_generate_attachment_metadata', 'upload_image_to_s3', 10, 2);
function upload_image_to_s3($metadata, $attachment_id) {
try {
$file = get_attached_file($attachment_id);
upload_to_s3($file);
$path_parts = pathinfo($file);
$path = $path_parts['dirname'];
$mime_type = get_post_mime_type($attachment_id);
if (strpos($mime_type, 'image') !== false) {
if (isset($metadata['sizes']) && is_array($metadata['sizes'])) {
foreach ($metadata['sizes'] as $size => $data) {
$file_size_path = $path.'/'.$data['file'];
upload_to_s3($file_size_path);
}
}
}
} catch (Exception $e) {
// Xử lý ngoại lệ ở đây nếu cần
error_log('Error: ' . $e->getMessage());
}
return $metadata;
}
Tới đây khi upload trong media của WordPress thì nó sẽ tự động lên s3 tất cả phiên bản của hình theo đúng đường dẫn uploads
Viết hàm xoá hình trên S3
function delete_from_s3($file_path) {
try {
// Chuẩn bị config S3
$bucket = S3_UPLOADS_BUCKET;
$s3 = new Aws\S3\S3Client([
'version' => 'latest',
'region' => S3_UPLOADS_REGION,
'credentials' => [
'key' => S3_UPLOADS_KEY,
'secret' => S3_UPLOADS_SECRET,
]
]);
$file_path = str_replace(UPLOAD_DIR, 'wp-content/uploads', $file_path);
// Thực hiện xoá file trên S3
$result = $s3->deleteObject([
'Bucket' => $bucket,
'Key' => $file_path,
]);
// Kiểm tra kết quả
if ($result['@metadata']['statusCode'] === 204) {
// Xoá thành công
return true;
} else {
// Xoá không thành công
return false;
}
} catch (Aws\S3\Exception\S3Exception $e) {
// Xử lý ngoại lệ
// Log lỗi hoặc thông báo cho người dùng
error_log('Error deleting file from S3: ' . $e->getMessage());
return false;
}
}
Sử dụng hook của wordpress để xoá hình
Hook này để báo cho WordPress biết khi xoá hình trên media thì cũng xoá luôn trên S3
add_action('delete_attachment', 'delete_image_to_s3');
function delete_image_to_s3($attachment_id) {
try {
$file = get_attached_file($attachment_id);
delete_from_s3($file);
$path_parts = pathinfo($file);
$path = $path_parts['dirname'];
$metadata = wp_get_attachment_metadata($attachment_id);
$mime_type = get_post_mime_type($attachment_id);
if (strpos($mime_type, 'image') !== false) {
if (isset($metadata['sizes']) && is_array($metadata['sizes'])) {
foreach ($metadata['sizes'] as $size => $data) {
$file_size_path = $path.'/'.$data['file'];
delete_from_s3($file_size_path);
}
}
}
} catch (Exception $e) {
// Xử lý ngoại lệ ở đây
error_log('Error deleting attachment: ' . $e->getMessage());
}
}
Sử dụng hook để replace lại đường dẫn hình mặc định của WordPress
Lúc này WordPress vẫn sử dụng đường dẫn cũ, nên cần replace qua đường dẫn S3, trường hợp có sài cloudfront thì bỏ qua bước này. Vì đường dẫn cloudfront sẽ giống với domain.
add_filter('upload_dir', 'custom_upload_dir');
function custom_upload_dir($upload) {
try {
$upload['baseurl'] = 'https://' . S3_UPLOADS_BUCKET . '.s3.'. S3_UPLOADS_REGION .'.amazonaws.com/wp-content/uploads';
} catch (Exception $e) {
// Xử lý ngoại lệ ở đây
error_log('Error setting custom upload directory: ' . $e->getMessage());
}
return $upload;
}
Tới đây mọi thứ đã xong, lưu ý là để chức năng chạy tốt thì khi lấy hình ra phải dùng hàm chuẩn của WordPress thì mới hook dc.