- vừa được xem lúc

Tối ưu upload file dung lượng lớn lên S3 bằng API

0 0 26

Người đăng: Nguyễn Anh Tiến

Theo Viblo Asia

Ở bài trước, mình đã giới thiệu chi tiết và đơn giản về bản chất của 3 loại Cloud Storage. Trong đó có Object storage là được ứng dụng rộng rãi nhất trong việc tích hợp với Web App, ứng dụng. Để xen kẽ với bài viết chia sẻ lý thuyết, mình sẽ giới thiệu chút thực hành cho các bạn biết code chút mong muốn ứng dụng luôn vào thực tế.

Ở bài viết này, mình sẽ sử dụng dịch vụ lưu trữ S3 Sun Simple Storage (Sun S3). Nếu các bạn muốn upload đơn giản hơn bằng giao diện, không cần tích hợp API thì có thể xem ở trang doc chính thức của Sunteco ở đây: https://docs.sunteco.vn/service/s3/how-to/hd-upload-object-bang-giao-dien.html

Còn sau đây sẽ là cách tích hợp API.

Tổng quan:

Với việc upload file bình thường, người dùng cần thực hiện ít nhất 3 request sau:

  1. Đầu tiên gọi API Pre-upload (/s3/v1/object/pre-upload) để lấy presigned URL

  2. Gọi phương thức PUT để upload file qua URL vừa nhận được để Object được upload trực tiếp lên Sun S3

  3. Gọi API Post-upload để hoàn thành upload

Giải thích thêm: Tại sao cần 3 bước với các API khác nhau mà không gộp chung lại làm 1 cái. Vì file dung lượng lớn nếu qua phía Backend rồi mới tới Sun S3 sẽ phải qua 2 lần upload sẽ tốn kém và tốc độ thấp hơn. Thêm nữa, việc mở ra chi tiết các API giúp bạn có thể thao tác, quản lý các part upload của mình.

Khi file muốn tải lên là file nặng (>=100MB), bạn nên sử dụng cơ chế upload thành nhiều phần (multipart upload) để:

  • Tránh việc bị Request Time Out
  • Upload đồng thời các phần sẽ cải thiện tốc độ
  • Có thể Stop và Resume việc upload và retry được 1 part bị lỗi mà k ảnh hưởng đến cả quá trình

Chúng ta sẽ tìm hiểu cụ thể cơ chế qua các bước. Ở đây bài viết sẽ dùng ReactJS để minh họa đơn giản cách làm, bạn hãy tham khảo để áp dụng linh hoạt vào project của mình.

Trước khi làm bạn nên mở thêm 1 tab API List trên trang dashboard sản phẩm https://dashboard.sunteco.vn/ để tiện tra cứu:

Steps:

Bước 1: Preview

Để có thể preview thuận tiện, bạn có thể sử dụng thư viện hỗ trợ việc lấy dữ liệu file lồng bên trong cây thư mục của folder kéo vào như "react-dropzone", thư viện này còn hỗ trợ việc kéo thả Drag and Drop file và folder.

Giờ sẽ tiến hành chia file để upload. Đầu tiên ta xác định dung lượng mỗi part, ở đây mình đặt là 50MB, sau đó xác định số part:

const FILE_SIZE_THRESH_SI = 1000;
const UPLOAD_CHUNK_SIZE = 50 * FILE_SIZE_THRESH_SI ** 2;
const partNum = Math.ceil(f.file.size / UPLOAD_CHUNK_SIZE);

Nếu số part > 1, người dùng sử dụng multipart, enum 2 loại upload như sau:

enum UploadTypeEnum { multiPart = "MultiplePart", singlePart = "SinglePart",
}

Từ đó có payload gọi API Pre-upload (/s3/v1/object/pre-upload) như sau:


{ bucketUniqcode: bucketUniqcode, items: prepareFiles.map((f) => { // detect multi parts upload const partNum = Math.ceil(f.file.size / UPLOAD_CHUNK_SIZE); return { name: f.file.name, folderPath: currentFolderPath, type: partNum > 1 ? UploadTypeEnum.multiPart : UploadTypeEnum.singlePart, numberOfParts: partNum > 1 ? partNum : undefined, }; }), }

Bước 2: Upload multipart lên Sun S3

Hãy xem đoạn code tham khảo sau đây:

const upPartPromises = (partItems ?? []).map(async (part) => { const start = ((part?.partNo ?? 1) - 1) * UPLOAD_CHUNK_SIZE; const end = (part?.partNo ?? 1) * UPLOAD_CHUNK_SIZE; const blob = file.slice(start, end); // file với type là File mà bạn up lên, tham khảo: https://developer.mozilla.org/en-US/docs/Web/API/Blob/slice const promise = axios.put( url: part.uploadUrl ?? "", upFile: blob, { headers: { "Content-Type": "multipart/form-data", }, onUploadProgress: (pEvent: ProgressEvent) => { if (pEvent.loaded === pEvent.total) { setProgress((pre) => pre + MAX_PERCENT / partNum); } }, }); return promise;
}); const resList = await Promise.all(upPartPromises);

Giải thích:

  • Đầu tiên ta chia file thành các blob dữ liệu, với mỗi blob sẽ upload lên 1 URL
  • Header có "Content-Type": "multipart/form-data", phương thức này còn giúp theo dõi được onUploadProgress để theo dõi % hoàn thành của từng part chính xác hơn
  • Như ở code mẫu sinh ra 1 mảng promise để có thể upload đồng thời các part cùng lúc, bạn cũng có thể kết hợp thêm batching khi số part cần upload nhiều lên

Sau đó response sẽ trả về list các presigned URL để người dùng chuẩn bị upload.

Result: Sau khi hoàn thành, Object mong muốn sẽ được thêm vào Bucket, bạn có thể lên trang dashboard của Sun S3 để kiểm tra lại.

Reference:

Hình minh họa đầu bài viết tham khảo từ https://magz.techover.io/2021/08/28/upload-file-dung-luong-lon-toi-s3-voi-multipart-va-presign-url/

Trang demo: dashboard.sunteco.vn

Bình luận

Bài viết tương tự

- vừa được xem lúc

PDF Export, cẩn thận với những input có thể truyền vào

Giới thiệu. Dạo gần đây mình tình cờ gặp rất nhiều lỗi XSS, tuy nhiên trang đó lại có sử dụng dữ liệu người dùng input vào để export ra PDF.

0 0 66

- vừa được xem lúc

Giới thiệu về AWS Batch

Khi sử dụng hệ thống cloud service, điều chúng ta thường phải quan tâm đến không chỉ là hiệu suất hoạt động (performance) mà còn phải chú ý đến cả chi phí bỏ ra để duy trì hoạt động của hệ thống. Chắn hẳn là hệ thống lớn hay nhỏ nào cũng đã từng phải dùng đến những instance chuyên để chạy batch thực

0 0 143

- vừa được xem lúc

Tìm hiểu về AWS KMS

1. AWS KMS là gì. Ở KMS bạn có thể lựa chọn tạo symetric key (khóa đối xứng) hoặc asymetric key (khóa bất đối xứng) để làm CMK (Customer Master Key). Sau khi tạo key thì có thể thiết đặt key policy để control quyền access và sử dụng key.

0 0 66

- vừa được xem lúc

AWS VPC cho người mới bắt đầu

Tuần này, tôi trình bày lại những gì tôi đã học được về Virtual Private Cloud (VPC) của Amazon. Nếu bạn muốn xem những gì tôi đã học được về AWS, hãy xem Tổng quan về DynamoDB và Tổng quan về S3. VPC là gì. Những điều cần lưu ý:.

0 0 84

- vừa được xem lúc

AWS Essentials (Phần 6): Guildline SNS Basic trên AWS

Tiếp tục với chuỗi bài viết về Basic AWS Setting, chúng ta tiếp tục tìm hiểu tiếp tới SNS (Simple Notification Service). Đây là một service của AWS cho phép người dùng setting thực hiện gửi email, text message hay push notification tự động tới mobile device dựa trên event người dùng setting phía AWS

0 0 145

- vừa được xem lúc

Sử dụng Amazon CloudFront Content Delivery Network với Private S3 Bucket — Signing URLs

Trong nhiều trường hợp, thì việc sử dụng CDN là bắt buộc. Mình đã trải nghiệm với một số CDN nhưng cuối cùng mình lựa chọn sử dụng AWS CloudFront.

0 0 117