Коротка відповідь
juniorEndpoint – це POST‑метод, що приймає multipart/form-data з полем file. Він читає потік даних у пам’ять, розраховує розмір і, якщо <=4 GB, передає його безпосередньо до S3 через SDK, використовуючи multipart upload. Якщо розмір перевищує ліміт, повертається 413 Request Entity Too Large.
Повне пояснення
Що це і навіщо
- Endpoint відповідає за отримання великих файлів від клієнта і їх зберігання у зовнішньому сховищі (S3, CDN). Це типова задача для бекендів, що працюють з медіа‑контентом.
Ключові принципи/терміни
multipart/form-data– формат, що дозволяє передавати файли у HTTP‑запиті.multipart upload– механізм S3, що розбиває великий файл на частини (parts) і завантажує їх паралельно.413 Request Entity Too Large– HTTP‑код, що сигналізує про перевищення дозволеного розміру.
Як це працює
- Клієнт надсилає POST‑запит з файлом у полі
file. - Сервер читає потік (
req.file.stream) і підраховує розмір. - Якщо розмір <= 4 GB, сервер викликає
s3.createMultipartUpload, отримуєuploadId. - Потім файл розбивається на частини (наприклад, 5 MB) і кожна частина надсилається через
s3.uploadPart. - Після успішного завантаження всіх parts сервер викликає
s3.completeMultipartUpload. - Якщо розмір перевищує 4 GB, сервер негайно повертає
413.
Практика і реалізація (Node.js / TypeScript)
import { S3Client, CreateMultipartUploadCommand, UploadPartCommand, CompleteMultipartUploadCommand } from "@aws-sdk/client-s3";
import { Readable } from "stream";
const s3 = new S3Client({ region: "us-east-1" });
export async function uploadLargeFile(fileStream: Readable, fileSize: number) {
if (fileSize > 4 * 1024 ** 3) throw new Error("413");
const create = await s3.send(new CreateMultipartUploadCommand({ Bucket: "my-bucket", Key: "file.bin" }));
const uploadId = create.UploadId!;
const parts: { ETag: string; PartNumber: number }[] = [];
let partNum = 1;
for await (const chunk of fileStream) {
const uploadPart = await s3.send(new UploadPartCommand({ Bucket: "my-bucket", Key: "file.bin", PartNumber: partNum, UploadId: uploadId, Body: chunk }));
parts.push({ ETag: uploadPart.ETag!, PartNumber: partNum });
partNum++;
}
await s3.send(new CompleteMultipartUploadCommand({ Bucket: "my-bucket", Key: "file.bin", UploadId: uploadId, MultipartUpload: { Parts: parts } }));
}
Тестування – можна використати jest з моками AWS SDK:
import { uploadLargeFile } from "./upload";
jest.mock("@aws-sdk/client-s3");
// ...тести, що перевіряють виклики CreateMultipartUploadCommand і UploadPartCommand
Безпека – перевірка MIME‑типу, обмеження розміру, використання IAM ролей з мінімальними правами.
Оптимізація – розмір частини 5–10 МБ, паралельне завантаження (параметр maxConcurrency у SDK).