Cách hook core upload file lên s3 trong Wordpress

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.

無料相談・お問い合わせ
insightscanXのお問い合わせもこちらからお願いします。
2025年1月からフリートライアル募集中
ご相談やお見積もりは全て 無料 で対応いたします。

    「個人情報保護方針」をお読みいただき同意いただける場合は「送信」ボタンを押して下さい。
    入力していただいたメールアドレス宛に自動返信メールを送信していますので、お手数ですがそちらをご確認ください。
    無料相談・お問い合わせ
    insightscanXのお問い合わせもこちらからお願いします。
    2025年1月からフリートライアル募集中
    ご相談やお見積もりは全て 無料 で対応いたします。

      「個人情報保護方針」をお読みいただき同意いただける場合は「送信」ボタンを押して下さい。
      入力していただいたメールアドレス宛に自動返信メールを送信していますので、お手数ですがそちらをご確認ください。
      無料相談
      お問い合わせ