Tải Lên Đa Phần (Multipart Upload) Tới S3 & Cloudflare R2 Bằng Node.js
Hướng dẫn từng bước sử dụng AWS SDK v3 trong Node.js để upload file lớn tới AWS S3 và Cloudflare R2. Tải kèm file mẫu 500MB để thử nghiệm.
Với các tệp lớn hơn 100MB, việc tải lên qua một request HTTP PutObject đơn lẻ rất dễ xảy ra lỗi. Chỉ một gói tin bị mất có thể khiến toàn bộ quá trình tải lên thất bại. AWS S3 và Cloudflare R2 cung cấp S3 Multipart Upload API, cho phép lập trình viên tải lên các phần độc lập song song và ghép chúng lại trên máy chủ.
Quy Trình Multipart Upload Chuẩn S3
- Khởi tạo (Initiate):
CreateMultipartUploadtrả về mộtUploadIdduy nhất. - Tải các phần (Upload Parts): Gửi các chunk từ 5MB đến 500MB bằng
UploadPartCommand. Mỗi phần trả về mộtETag. - Hoàn tất (Complete): Gửi
CompleteMultipartUploadCommandkèm danh sách PartNumber và ETag đã sắp xếp theo thứ tự.
Tải file PDF mẫu 500MB để kiểm thử và đo hiệu năng pipeline multipart upload S3/R2 của bạn.
Tải File Mẫu 500MB PDF →Triển Khai Bằng AWS SDK v3 Trong Node.js
import {
S3Client,
CreateMultipartUploadCommand,
UploadPartCommand,
CompleteMultipartUploadCommand,
AbortMultipartUploadCommand,
} from '@aws-sdk/client-s3';
import fs from 'fs';
const s3 = new S3Client({
region: 'auto',
endpoint: process.env.R2_ENDPOINT, // e.g. https://<accountId>.r2.cloudflarestorage.com
credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
},
});
export async function uploadLargeFileToR2(filePath: string, bucket: string, key: string) {
const PART_SIZE = 10 * 1024 * 1024; // 10MB mỗi phần (phải >= 5MB với S3/R2)
const fileStats = fs.statSync(filePath);
const fileStream = fs.createReadStream(filePath, { highWaterMark: PART_SIZE });
// 1. Khởi tạo Multipart Upload
const init = await s3.send(
new CreateMultipartUploadCommand({
Bucket: bucket,
Key: key,
})
);
const uploadId = init.UploadId;
const uploadedParts: { PartNumber: number; ETag: string }[] = [];
let partNumber = 1;
try {
for await (const chunk of fileStream) {
console.log(`Đang tải phần ${partNumber}...`);
const partResult = await s3.send(
new UploadPartCommand({
Bucket: bucket,
Key: key,
UploadId: uploadId,
PartNumber: partNumber,
Body: chunk,
})
);
uploadedParts.push({
PartNumber: partNumber,
ETag: partResult.ETag!,
});
partNumber++;
}
// 2. Hoàn tất Upload
await s3.send(
new CompleteMultipartUploadCommand({
Bucket: bucket,
Key: key,
UploadId: uploadId,
MultipartUpload: {
Parts: uploadedParts.sort((a, b) => a.PartNumber - b.PartNumber),
},
})
);
console.log('Tải lên hoàn tất thành công!');
} catch (error) {
console.error('Tải lên thất bại. Đang hủy multipart upload...', error);
await s3.send(
new AbortMultipartUploadCommand({
Bucket: bucket,
Key: key,
UploadId: uploadId,
})
);
throw error;
}
}
Các Quy Tắc Vận Hành Thực Chiến
- Kích thước phần tối thiểu: Tất cả các phần trừ phần cuối cùng phải có dung lượng ít nhất 5MB (5.242.880 byte). Gửi một phần nhỏ hơn 5MB sẽ gây lỗi
EntityTooSmall. - Luôn xử lý hủy (abort): Các phần multipart chưa hoàn chỉnh vẫn tồn tại trong object storage và bị tính phí lưu trữ hàng tháng cho đến khi bị hủy. Thiết lập Lifecycle Rules trên S3/R2 để tự động xóa các multipart upload chưa hoàn tất sau 7 ngày.
Nguyễn Đại Long
Tác GiảBackend Lead • Chuyên gia Kiến trúc Hệ thống Phân tán & Lưu trữ Đám mây
Hơn 4 năm kinh nghiệm thiết kế các hệ thống xử lý tệp tải lên thông lượng lớn, tối ưu hóa cơ sở dữ liệu và hạ tầng phân tán Cloudflare R2 / AWS S3. Người sáng lập FileDummy và Mạng lưới Hệ sinh thái NDL.
Bài viết này có hữu ích không?
Bấm Thích để ủng hộ tác giả và giúp bài viết lan tỏa tới cộng đồng lập trình viên.
Thảo Luận Kỹ Thuật & Đóng Góp Ý Kiến (0)
Chia sẻ kết quả benchmark, phản hồi các trường hợp biên hoặc đặt câu hỏi chuyên môn.
Chưa có bình luận nào. Hãy là lập trình viên đầu tiên bắt đầu cuộc thảo luận!
Câu Hỏi Thường Gặp (FAQ)
What is the minimum part size for S3 multipart uploads?▾
Each part (except the last) must be at least 5MB. Parts smaller than 5MB result in an EntityTooSmall error on CompleteMultipartUpload. Cloudflare R2 follows the same S3-compatible constraint.
How many parts can a single S3 multipart upload have?▾
A maximum of 10,000 parts per upload. With 5MB minimum part size, this gives a theoretical maximum object size of approximately 50GB.
How do I cancel a multipart upload?▾
Always call AbortMultipartUpload on failure or user cancellation. Incomplete parts accrue storage costs on both S3 and R2. Use S3 Lifecycle rules to auto-abort incomplete uploads after N days.