File manager kiểu Google Drive, chạy trên Cloudflare Pages + Pages Functions, lưu file trên Cloudflare R2 của chính bạn. Không có server database nào lưu trữ dữ liệu người dùng — mọi thứ đi thẳng từ trình duyệt tới R2.
- Vào Cloudflare Dashboard → R2 → Create bucket.
- Đặt tên bucket (ví dụ
my-drive), Location tuỳ ý.
- Vẫn ở trang R2 → Manage API Tokens → Create API Token.
- Chọn quyền Object Read & Write.
- Ở phần "Specify bucket(s)", chọn đúng bucket vừa tạo (giới hạn quyền cho an toàn).
- Bấm Create API Token → Cloudflare hiện ra 3 giá trị, copy lại ngay (Secret Access Key chỉ hiện 1 lần):
Account IDAccess Key IDSecret Access Key
Vì trình duyệt sẽ upload/tải file trực tiếp vào R2 (qua presigned URL), bucket cần cho phép domain Cloudflare Pages của bạn gọi tới. Vào bucket → Settings → CORS Policy → dán:
[
{
"AllowedOrigins": ["https://ten-project-cua-ban.pages.dev"],
"AllowedMethods": ["GET", "PUT", "DELETE"],
"AllowedHeaders": ["*"],
"ExposeHeaders": ["ETag"],
"MaxAgeSeconds": 3600
}
]Thay
https://ten-project-cua-ban.pages.devbằng domain thật sau khi deploy xong ở bước 4 (bạn có thể deploy trước, lấy domain, rồi quay lại cấu hình CORS). Nếu dùng domain riêng, thêm cả domain đó vàoAllowedOrigins.
- Tạo 1 repo GitHub mới, push toàn bộ thư mục này lên.
- Vào Cloudflare Dashboard → Workers & Pages → Create → Pages → Connect to Git.
- Chọn repo vừa tạo. Ở phần build settings:
- Framework preset:
None - Build command: để trống
- Build output directory:
public
- Framework preset:
- Bấm Save and Deploy. Cloudflare sẽ tự chạy
npm installđể càiaws4fetchcho Pages Functions. - Sau khi deploy xong, bạn sẽ có domain dạng
https://ten-project.pages.dev— quay lại bước 3 để điền đúng domain vào CORS.
- Mở domain vừa deploy.
- Lần đầu tiên: điền
Account ID,Access Key ID,Secret Access Key,Bucket name(bước 2), rồi đặt Username + Password để khoá màn hình cho lần sau. - Các lần vào sau chỉ cần nhập Username + Password.
- 4 thông tin R2 được mã hoá bằng AES-GCM (khoá suy ra từ password qua PBKDF2, 200,000 vòng)
ngay trên trình duyệt, rồi mới lưu vào
localStorage. Password không được lưu ở đâu cả. - Nếu quên password: không có cách khôi phục (không có server nào giữ bản sao) — bạn cần xoá dữ liệu trình duyệt và nhập lại 4 thông tin R2 từ đầu.
- Đây không phải hệ thống đăng nhập nhiều người dùng có máy chủ xác thực — mỗi trình duyệt lưu 1 bộ dữ liệu riêng, không đồng bộ giữa các thiết bị.
- Folder được mô phỏng bằng key-prefix của R2 (giống S3), giữ folder rỗng bằng 1 file ẩn
.keep. - Upload/xem/tải file đi thẳng trình duyệt ↔ R2 qua presigned URL (không qua server trung gian), nên không bị giới hạn dung lượng của Pages Functions.
- Các thao tác tạo folder / xoá / đổi tên đi qua Pages Functions vì cần dùng Secret Access Key để ký request — key này chỉ dùng tức thời trong request, không được lưu hay log lại phía server.
public/ → giao diện (HTML/CSS/JS thuần)
functions/api/ → Cloudflare Pages Functions (proxy ký request tới R2)
package.json → khai báo dependency aws4fetch
Vì môi trường tạo project này không có kết nối mạng để gọi thử API R2 thật, hãy deploy và test kỹ
từng chức năng (tạo folder, upload, xem preview ảnh/video, đổi tên, xoá) trên bucket thật của bạn.
Nếu gặp lỗi ký request (SignatureDoesNotMatch hoặc tương tự), thường là do version aws4fetch
hoặc cấu hình CORS — kiểm tra lại bước 3 trước tiên.