← назад к разделу

AWS SDK v3 разделен на небольшие пакеты. Для S3 используют S3Client и команды, а не глобальный объект AWS со всеми сервисами сразу.

Запись объекта

PutObjectCommand принимает тело строкой, buffer или stream. Для большого файла используют stream и не читают его целиком в память.

import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
import { createReadStream } from 'node:fs';

const s3 = new S3Client({ region: process.env.AWS_REGION });

await s3.send(new PutObjectCommand({
  Bucket: process.env.UPLOAD_BUCKET,
  Key: 'exports/orders-2026-10.ndjson',
  Body: createReadStream('/tmp/orders.ndjson'),
  ContentType: 'application/x-ndjson',
}));

Key - полное имя объекта, включая префикс. Bucket и ключ не выводят из пользовательского ввода без правил: иначе один клиент сможет перезаписать чужой объект.

Multipart и поток

Upload из @aws-sdk/lib-storage разбивает большой объект на части и выполняет multipart upload. Он подходит для потоковой записи, но требует явного контроля параллелизма и размера части.

При ошибке неполная multipart-загрузка может остаться в bucket. Lifecycle-правило AbortIncompleteMultipartUpload удаляет такие части через заданный срок; это отдельная настройка стоимости.

Чтение и signed URL

GetObjectCommand возвращает поток тела. Читать его нужно как stream и закрывать после обработки.

Если объект приватный, приложение не отдает файл через свой сервер без необходимости: выдает короткую presigned URL.

import { GetObjectCommand } from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';

const url = await getSignedUrl(
  s3,
  new GetObjectCommand({
    Bucket: process.env.UPLOAD_BUCKET,
    Key: 'exports/orders-2026-10.ndjson',
  }),
  { expiresIn: 600 },
);

URL действует десять минут. Она не делает объект публичным и не заменяет проверку прав перед выдачей. Просроченную ссылку нельзя «отозвать», поэтому срок и аудит важны.

Коротко

  • SDK v3 использует отдельные клиенты и команды.
  • Большие тела передают stream или multipart, а не целиком в память.
  • Незавершенные multipart удаляет lifecycle-правило.
  • Presigned URL ограничена сроком и требует проверки прав.
  • Ключи и права проверяют, чтобы не перезаписать чужие объекты.

Что почитать дальше