1. Tạo Bucket và Cấu hình Quyền Truy cập
Chúng ta bắt đầu bằng việc tạo một bucket mới để chứa dữ liệu, đồng thời thiết lập chính sách quyền truy cập (public/private) ngay từ đầu.
Thực hiện tạo bucket có tên demo-assets với chế độ mặc định là private (chỉ chủ sở hữu hoặc người được ủy quyền mới truy cập được).
curl -X PUT "http://localhost:8080/demo-assets" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"acl": "private", "versioning": true}'
Kết quả mong đợi: HTTP status code 201 Created với body JSON xác nhận bucket đã được tạo, chứa trường name là demo-assets và acl là private.
Để tạo bucket công khai (public-read), cho phép ai cũng có thể GET file nhưng không được PUT/DELETE, thực hiện lệnh sau:
curl -X PUT "http://localhost:8080/public-images" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"acl": "public-read"}'
Kết quả mong đợi: HTTP status code 201 Created. Bucket này sẽ cho phép truy cập trực tiếp qua URL mà không cần token cho các request GET.
Verify kết quả bằng cách liệt kê tất cả bucket hiện có trong hệ thống:
curl -X GET "http://localhost:8080/buckets" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN_HERE"
Kết quả mong đợi: Danh sách JSON chứa ít nhất 2 bucket: demo-assets và public-images với các thuộc tính ACL tương ứng.
2. Upload File Đơn và File Lớn
Thực hiện upload file đơn giản (dưới 5MB) để kiểm tra luồng dữ liệu cơ bản vào bucket demo-assets.
Tạo một file mẫu nội dung văn bản để upload:
echo "This is a test file for PostgreSQL Object Store" > /tmp/test-document.txt
Sử dụng lệnh curl để upload file này vào bucket, đặt tên object là documents/test-document.txt:
curl -X PUT "http://localhost:8080/demo-assets/documents/test-document.txt" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN_HERE" \
-H "Content-Type: text/plain" \
--data-binary @/tmp/test-document.txt
Kết quả mong đợi: HTTP status code 200 OK hoặc 201 Created. Body phản hồi chứa ETag (hash của file) và LastModified.
Đối với file lớn (lớn hơn 100MB), chúng ta sử dụng cơ chế Multipart Upload để chia nhỏ file thành các phần (parts) và upload song song, tránh timeout.
Bước 1: Khởi tạo một session upload multipart cho file lớn:
curl -X POST "http://localhost:8080/demo-assets/large-video.mp4?uploads" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN_HERE" \
-H "Content-Type: application/octet-stream"
Kết quả mong đợi: JSON trả về chứa UploadId (ví dụ: 550e8400-e29b-41d4-a716-446655440000).
Bước 2: Giả sử file đã được chia nhỏ, upload Part 1 (dữ liệu giả lập):
curl -X PUT "http://localhost:8080/demo-assets/large-video.mp4?uploadId=YOUR_UPLOAD_ID&partNumber=1" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN_HERE" \
-H "Content-Type: application/octet-stream" \
--data-binary @/tmp/part1.bin
Kết quả mong đợi: HTTP status code 200 OK và header ETag cho phần này.
Bước 3: Hoàn tất (Complete) quá trình upload bằng cách gửi danh sách tất cả ETag của các phần đã upload:
curl -X POST "http://localhost:8080/demo-assets/large-video.mp4?uploadId=YOUR_UPLOAD_ID" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN_HERE" \
-H "Content-Type: application/xml" \
--data-binary @-
Kết quả mong đợi: HTTP status code 200 OK với body chứa thông tin object hoàn chỉnh đã được hợp nhất.
3. Xác minh Dữ liệu trong PostgreSQL
Để đảm bảo dữ liệu đã được Object Store lưu trữ chính xác vào cơ sở dữ liệu PostgreSQL, chúng ta sẽ truy vấn trực tiếp các bảng hệ thống.
Kết nối vào PostgreSQL với quyền postgres hoặc user có quyền đọc schema của Object Store:
sudo -u postgres psql -d object_store_db -c "SELECT bucket_name, object_name, size, content_type, created_at FROM objects WHERE bucket_name = 'demo-assets';"
Kết quả mong đợi: Bảng kết quả hiển thị các dòng tương ứng với test-document.txt và large-video.mp4 (nếu đã complete), với cột size khớp với kích thước file thực tế.
Kiểm tra chi tiết metadata và lưu trữ nội dung (blob) trong bảng nội dung (tùy theo thiết kế schema phần 2, thường là bảng object_content hoặc blobs):
sudo -u postgres psql -d object_store_db -c "SELECT id, object_id, checksum, storage_type FROM object_content WHERE object_id = (SELECT id FROM objects WHERE object_name = 'documents/test-document.txt');"
Kết quả mong đợi: Thấy record với checksum khớp với ETag nhận được khi upload, xác nhận tính toàn vẹn của dữ liệu.
Đối với file lớn, kiểm tra bảng multipart_uploads hoặc object_parts để đảm bảo các phần đã được hợp nhất và xóa thông tin tạm:
sudo -u postgres psql -d object_store_db -c "SELECT upload_id, status FROM multipart_uploads WHERE bucket_name = 'demo-assets';"
Kết quả mong đợi: Status của upload đã hoàn thành phải là COMPLETED hoặc record đã bị xóa (tùy logic cleanup của hệ thống).
4. Quản lý Object: List, Download và Xóa
Thực hiện liệt kê (List) các object trong bucket demo-assets để xem cấu trúc thư mục ảo và danh sách file.
Yêu cầu list với prefix documents/ để lọc theo thư mục:
curl -X GET "http://localhost:8080/demo-assets?prefix=documents/" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN_HERE"
Kết quả mong đợi: JSON chứa danh sách Contents với Key là documents/test-document.txt và CommonPrefixes nếu có nhiều folder con.
Thực hiện download (GET) file đã upload để kiểm tra nội dung:
curl -X GET "http://localhost:8080/demo-assets/documents/test-document.txt" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN_HERE" \
-o /tmp/downloaded-test.txt
Kiểm tra nội dung file đã tải về so với file gốc:
diff /tmp/test-document.txt /tmp/downloaded-test.txt
Kết quả mong đợi: Không có đầu ra (diff không báo lỗi), nghĩa là nội dung file giống hệt nhau.
Thử download file từ bucket public (public-images) mà không cần token (nếu đã upload file vào đó):
curl -X GET "http://localhost:8080/public-images/sample.jpg" -o /tmp/public-sample.jpg
Kết quả mong đợi: HTTP status code 200 OK (không cần header Authorization).
Thực hiện xóa (Delete) object không cần thiết khỏi bucket:
curl -X DELETE "http://localhost:8080/demo-assets/documents/test-document.txt" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN_HERE"
Kết quả mong đợi: HTTP status code 204 No Content.
Verify việc xóa bằng cách thử GET file vừa xóa:
curl -X GET "http://localhost:8080/demo-assets/documents/test-document.txt" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN_HERE"
Kết quả mong đợi: HTTP status code 404 Not Found hoặc JSON lỗi NoSuchKey.
Kiểm tra lại trong PostgreSQL để đảm bảo record đã bị xóa khỏi bảng objects:
sudo -u postgres psql -d object_store_db -c "SELECT count(*) FROM objects WHERE object_name = 'documents/test-document.txt';"
Kết quả mong đợi: Count trả về là 0.
Điều hướng series:
Mục lục: Series: Triển khai Database Object Store với PostgreSQL và Ubuntu 24.04
« Phần 4: Cấu hình bảo mật và quản lý truy cập cho Object Store
Phần 6: Cấu hình replication và backup dữ liệu Object Store »