Multipart upload biến một file lớn thành nhiều part có thể tải song song và retry độc lập. Nhưng một hệ thống production không thể chỉ “chia file rồi upload”: nó phải giữ chính xác uploadId, part number và ETag, xác minh checksum, giới hạn concurrency, hoàn tất theo thứ tự, đồng thời abort mọi phiên thất bại để không tích lũy chi phí lưu trữ vô hình.
Bài viết bám theo tài liệu chính thức về Amazon S3 multipart upload, kiểm tra tính toàn vẹn và abort upload chưa hoàn tất. S3-compatible storage có thể khác về checksum, presigned URL và giới hạn; luôn test với nhà cung cấp đích.
1. Vòng đời ba bước và trạng thái phải lưu
- Initiate: tạo phiên, khai báo metadata/checksum và nhận
uploadId. - Upload parts: gửi từng part với
partNumber, lưu ETag/checksum trả về. - Complete: gửi danh sách part number và ETag để S3 ghép object.
Nếu không thể complete, client hoặc backend phải gọi abort. Object chỉ xuất hiện sau complete thành công; các part đang dang dở vẫn chiếm dung lượng và bị tính phí. Trạng thái resume tối thiểu gồm bucket, key, upload ID, part size, file fingerprint, danh sách part đã hoàn thành và thuật toán checksum.
2. Chọn part size bằng giới hạn, không bằng cảm tính
Part quá nhỏ làm tăng số request, metadata và thời gian complete; part quá lớn làm retry tốn thời gian và giảm mức song song. Tính kích thước từ dung lượng file, giới hạn số part của dịch vụ và memory budget:
part_size = max(provider_minimum,
ceil(file_size / safe_max_parts),
application_default)
AWS thường khuyến nghị cân nhắc multipart từ khoảng 100 MB. Đây không phải ngưỡng bắt buộc cho mọi workload. Browser di động, mạng yếu, proxy và S3-compatible gateway cần benchmark riêng. Ngoại trừ part cuối, các part phải đáp ứng minimum size của provider.
3. Concurrency phải có giới hạn
Tăng worker không làm băng thông tăng vô hạn. Quá nhiều part song song gây memory spike, socket exhaustion, throttling và cạnh tranh uplink. Khởi đầu với concurrency nhỏ, đo throughput/error rồi điều chỉnh.
- Đọc file theo slice/stream, không nạp toàn bộ vào RAM.
- Giới hạn số part đang bay và tổng byte đang buffer.
- Retry từng part với exponential backoff và jitter.
- Không retry vô hạn lỗi quyền, checksum hoặc request sai.
- Tôn trọng cancellation và deadline của người dùng.
4. Resume an toàn cần fingerprint file
Không được dùng lại phiên chỉ vì tên file giống nhau. File có thể đã thay đổi giữa hai lần mở trình duyệt. Lưu fingerprint từ size, last-modified và checksum thích hợp; trước khi resume, đối chiếu với file hiện tại.
Gọi ListParts để reconcile với trạng thái server thay vì tin tuyệt đối local storage. Server là nguồn sự thật về part đã nhận. Nếu cùng part number được upload lại, phiên bản mới thay part cũ; vì vậy một race giữa hai client resume có thể làm object cuối sai nếu không có lease hoặc session owner.
5. Complete là thao tác cần idempotency ở tầng ứng dụng
Client có thể timeout dù S3 đã complete. Không nên lập tức initiate phiên mới. Backend cần lưu trạng thái completing/completed, kiểm tra object bằng HeadObject và đối chiếu checksum/metadata trước khi quyết định retry.
Danh sách complete phải đúng part number và ETag trả về. Khi dùng checksum multipart, tài liệu AWS yêu cầu part number liên tiếp bắt đầu từ 1. Sắp xếp theo part number, không theo thời gian hoàn tất vì upload song song có thể trả kết quả lộn thứ tự.
6. ETag không phải lúc nào cũng là MD5
Không coi ETag của multipart object là MD5 toàn file. Encryption, multipart và implementation của provider có thể làm giả định đó sai. Chọn checksum được API hỗ trợ như SHA-256 hoặc CRC phù hợp, gửi checksum đúng contract và đọc lại metadata sau complete.
| Lớp kiểm tra | Mục tiêu |
|---|---|
| Checksum từng part | Phát hiện part hỏng trên đường truyền |
| Full-object checksum | Xác nhận object cuối đúng byte |
| Size/metadata | Phát hiện nhầm file hoặc nhầm phiên |
| Ứng dụng đọc thử | Xác nhận định dạng có thể sử dụng |
7. Presigned URL không được biến backend thành proxy file
Với browser/mobile, backend có thể authorize phiên và cấp presigned URL cho từng part; client upload thẳng tới object storage. Backend vẫn sở hữu policy:
- key do server sinh, không tin đường dẫn tùy ý từ client;
- giới hạn content length, loại file và quota người dùng;
- URL sống ngắn, chỉ áp dụng đúng bucket/key/uploadId/partNumber;
- complete chỉ được phép cho owner của phiên;
- không trả credential cloud dài hạn xuống client.
CORS phải chỉ cho origin, method và header cần thiết. Presigned URL là bearer capability trong thời gian hiệu lực; không ghi nó vào analytics, ticket hoặc log công khai.
8. Cleanup có hai lớp
Ứng dụng nên abort ngay khi người dùng hủy hoặc workflow thất bại vĩnh viễn. Bucket lifecycle là lưới an toàn để abort incomplete multipart uploads cũ sau số ngày đã chọn. Lifecycle không thay cho cleanup chủ động vì part vẫn bị tính phí trong cửa sổ chờ.
Chạy job inventory định kỳ: số phiên mở, tuổi lớn nhất, tổng byte part chưa hoàn tất, owner và nguyên nhân. Khi abort, nhớ rằng part request đang bay vẫn có thể kết thúc; phối hợp cancellation trước rồi mới cleanup theo hướng dẫn provider.
9. Bảo mật và xử lý sau upload
- IAM chỉ cấp initiate/upload/list/complete/abort trên prefix cần thiết.
- Mã hóa at rest và TLS in transit theo policy.
- Object mới vào vùng quarantine nếu cần antivirus/content validation.
- Không phục vụ file bằng Content-Type do client tự khai báo mà chưa kiểm tra.
- Tên hiển thị tách khỏi object key để tránh path injection.
- Audit ai tạo, complete hoặc abort phiên.
10. Observability và kiểm thử failure
Theo dõi bytes/second, duration, retry theo status, checksum failure, complete failure, abort failure, số upload mở và storage của orphan parts. Phân biệt lỗi client, network, throttling và provider.
Test bằng cách ngắt mạng giữa part, restart client, upload lại cùng part, timeout đúng lúc complete, đổi file trước resume, hết hạn presigned URL, thiếu IAM permission và lifecycle cleanup. Một demo chạy trên Wi-Fi ổn định không đủ chứng minh production.
Checklist production
- Part size và concurrency được tính theo file, RAM và giới hạn provider.
- Resume state có file fingerprint, upload ID, part number, ETag/checksum.
ListPartsđược dùng để reconcile.- Complete sắp xếp part đúng thứ tự và có xử lý timeout idempotent.
- Checksum được xác minh; không dùng ETag như MD5 toàn file.
- Presigned URL scope hẹp, sống ngắn và không lộ credential.
- Ứng dụng abort chủ động; bucket có lifecycle cleanup.
- Object được validate/quarantine trước khi phục vụ nếu cần.
- Metric và alert phát hiện orphan upload lẫn chi phí tăng.
- Đã test mất mạng, crash, retry, resume và complete không rõ kết quả.
Kết luận
Multipart upload đáng tin cậy là một state machine, không chỉ là phép chia file. Khi quản lý đúng identity của phiên, giới hạn concurrency, reconcile part, xác minh checksum và bảo đảm complete-or-abort, hệ thống vừa phục hồi tốt trên mạng yếu vừa tránh object sai và hóa đơn từ những part bị quên.




Chưa có bình luận. Hãy là người đầu tiên chia sẻ ý kiến.