- PVSM.RU - https://www.pvsm.ru -

Мультипарт-загрузка в объектное хранилище Selectel: пишем тривиальный пример на Python

Мультипарт-загрузка в объектное хранилище Selectel: пишем тривиальный пример на Python - 1

Объектные хранилища с доступом на базе S3 API — это, возможно, лучшее решение для хранения больших объемов данных. Однако при загрузке крупных файлов могут возникнуть проблемы. Например, долгая передача данных из-за сетевых ограничений или таймауты и обрывы соединения. Как ни крути, а интернет даже здесь диктует свои условия. Попробуем их обойти с помощью мультипарт-загрузки.

Привет! Меня зовут Гришин Александр, я продакт-менеджер в Selectel и отвечаю за развитие объектного хранилища и облачных баз данных. В этой статье я расскажу, как загружать большие файлы в S3 с помощью мультипарт-загрузки, используя Python и boto3. Под катом вы узнаете, как работает этот механизм и как его настроить для эффективной работы.

Мультипарт-загрузка в объектное хранилище Selectel: пишем тривиальный пример на Python - 2Скоро выпустим новый комикс о путешествиях ИБ-специалиста! Регистрируйтесь [1], чтобы узнать о публикации первыми. Бонусом сможете выиграть один из 15 комплектов призов.

Используйте навигацию, если не хотите читать текст полностью:
Как работает мультипарт-загрузка в S3 [2]
Пример на Python [3]
Оптимизация и рекомендации [4]
А нужен ли код [5]

Как работает мультипарт-загрузка в S3


Мультипарт-загрузка состоит из нескольких этапов.
1. Инициализация загрузки [6] — создание уникального идентификатора загрузки.

response = s3_client.create_multipart_upload(Bucket=BUCKET_NAME, Key=KEY)
upload_id = response["UploadId"]

Этот запрос создает мультипарт-загрузку и возвращает UploadId, который используется для загрузки частей файла.
2. Разделение файла на части и их параллельная отправка [7].

response = s3_client.upload_part(
                Bucket=BUCKET_NAME,
                Key=KEY,
                PartNumber=part_number,
                UploadId=upload_id,
                Body=data
            )

3. Завершение загрузки [8] и сборка частей в единый объект:

s3_client.complete_multipart_upload(
        Bucket=BUCKET_NAME,
        Key=KEY,
        UploadId=upload_id,
        MultipartUpload={"Parts": parts}
    )

4. При необходимости — отмена загрузки (например, если загрузка не удалась).

Мультипарт-загрузка в объектное хранилище Selectel: пишем тривиальный пример на Python - 3

Схема разбиения объекта на парты и их параллельная загрузка в S3.

Мультипарт-загрузка в объектное хранилище Selectel: пишем тривиальный пример на Python - 4

Пример на Python


Реализацию мультипарт-загрузки я разделю на два этапа: работа в панели управления и работа на клиенте. Итак.

Часть работы в панели управления Selectel

В целом, здесь нам нужно просто создать и настроить контейнер объектного хранилища. Очень подробный пошаговый гайд вы найдете в недавней статье [9] моего коллеги. Я же перечислю только основные шаги:

  1. Перейдите в панель управления [10]Объектное хранилище и нажмите Создать контейнер.
  2. Выберите тип адресации vHosted. Что касается типа контейнера, то для работы с чувствительными данными подойдет приватный, а если планируете реализовать доступ к контенту без авторизации, выберите публичный.
  3. Создайте служебного пользователя с ролью администратор объектного хранилища и доступом в нужный проект.
  4. Создайте S3-ключ в панели управления.
  5. Сохраните Access Key и Secret Key (будьте внимательны: ключи не хранятся в наших системах и показываются только один раз).

Мультипарт-загрузка в объектное хранилище Selectel: пишем тривиальный пример на Python - 5

Работа с сервисными пользователями в панели управления.

Часть работы на клиенте

Прежде всего, установите библиотеку boto3. Это делается командой в терминале:

pip install boto3

Теперь подключаем библиотеки и пишем код для загрузки файла в объектное хранилище, используя мультипарт-загрузку:

import boto3
import os
# Настройки подключения к Selectel S3
S3_ENDPOINT = "https://s3.ru-1.storage.selcloud.ru"  # Укажите ваш региональный endpoint
ACCESS_KEY = "ТУТ_ВАШ_ACCESS_KEY"
SECRET_KEY = "ТУТ_ВАШ_SECRET_KEY"
BUCKET_NAME = "4habr"
FILE_PATH = "/Users/alex/Downloads/1.mp4"  # Файл для загрузки
KEY = "thebigboy2.mp4"  # Название объекта в S3

# Создаем S3 клиент
s3_client = boto3.client(
    "s3",
    endpoint_url=S3_ENDPOINT,
    aws_access_key_id=ACCESS_KEY,
    aws_secret_access_key=SECRET_KEY
)

# 1. Инициализация мультипартийной загрузки
response = s3_client.create_multipart_upload(Bucket=BUCKET_NAME, Key=KEY)
upload_id = response["UploadId"]

print(f"Multipart Upload ID: {upload_id}")

# 2. Разбиение файла на части и загрузка
PART_SIZE = 1 * 1024 * 1024  # Размер одной части (1MB)
parts = []
file_size = os.path.getsize(FILE_PATH)

try:
    with open(FILE_PATH, "rb") as f:
        part_number = 1
        while True:
            data = f.read(PART_SIZE)
            if not data:
                break

            # Загружаем часть файла
            response = s3_client.upload_part(
                Bucket=BUCKET_NAME,
                Key=KEY,
                PartNumber=part_number,
                UploadId=upload_id,
                Body=data
            )

            # Добавляем информацию о части
            parts.append({"PartNumber": part_number, "ETag": response["ETag"]})
            print(f"Uploaded part {part_number}")
            part_number += 1

    # 3. Завершаем загрузку
    s3_client.complete_multipart_upload(
        Bucket=BUCKET_NAME,
        Key=KEY,
        UploadId=upload_id,
        MultipartUpload={"Parts": parts}
    )

    print("Multipart upload completed!")

except Exception as e:
    print("Upload failed:", str(e))
    s3_client.abort_multipart_upload(Bucket=BUCKET_NAME, Key=KEY, UploadId=upload_id)

Как работает этот код:

  • create_multipart_upload — создаем загрузку и получаем UploadId;
  • читаем файл частями по 1 МБ и загружаем их с помощью upload_part;
  • сохраняем ETag загруженных частей для финальной сборки;
  • complete_multipart_upload — объединяем загруженные части в единый объект;
  • если произошла ошибка, вызываем abort_multipart_upload для отмены загрузки.

Результат

Объект загружен [11]. Можно делиться им с друзьями. Чтобы увидеть результат работы со стороны хранилища, снова зайдите в панель управления. Перейдите в нужный проект в объектном хранилище и включите отображение служебных контейнеров в настройках (это необходимо, чтобы увидеть парты загруженного объекта). В основном контейнере вы увидите ссылку на загруженный объект, а в служебном — парты этого объекта. На скриншоте ниже это шесть объектов размером до 1 МБ.

Мультипарт-загрузка в объектное хранилище Selectel: пишем тривиальный пример на Python - 6

Листинг мультипартов в интерфейсе хранилища.

Оптимизация и рекомендации


Для примера выше я установил размер парта 1 МБ, но это было сделано умышленно с целью демонстрации. Не стоит это повторять. В реальных проектах для загрузки больших файлов лучше использовать значения существенно больше, хотя бы 50-100 МБ.

Для обработки ошибок добавьте повторную попытку загрузки парта в случае сетевых проблем. А также настройте удаление ненужных частей в случае таких ошибок. В Selectel мы всегда храним все составные части загрузки, поскольку не знаем, в какой момент со стороны клиента может прийти CompleteMultipartUpload [8] и нужны ли еще клиенту эти части.

А нужен ли код


В этой статья я использовал код только для демонстрации работы мультипартовой загрузки в объектное хранилище Selectel [12]. Для большего удобства рекомендую использовать готовые приложения, поддерживающие такую функциональность из коробки. К ним относятся:

Пользуясь случаем, выделю именно rclone т. к. недавно мы стали официальными технологическими партнерами [18] и получили нативную поддержку нашей услуги в этом клиенте.

Если у вас остались вопросы, смело задавайте их в комментариях, все обсудим. И поделитесь своим опытом, как вы ускоряете загрузку ваших приложений в объектное хранилище.

Автор: GrishinAlex

Источник [19]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/python/412773

Ссылки в тексте:

[1] Регистрируйтесь: https://promo.selectel.ru/multihacker/?utm_source=habr.com&utm_medium=referral&utm_campaign=comics_article_multiparts3_040325_banner_072_02_ord

[2] Как работает мультипарт-загрузка в S3: #1

[3] Пример на Python: #2

[4] Оптимизация и рекомендации: #3

[5] А нужен ли код: #4

[6] Инициализация загрузки: https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html

[7] отправка: https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html

[8] Завершение загрузки: https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html

[9] в недавней статье: https://habr.com/ru/companies/selectel/articles/875956/%232

[10] в панель управления: https://my.selectel.ru/?utm_source=habr.com&utm_medium=referral&utm_campaign=myselectel_article_multiparts3_040325_banner

[11] Объект загружен: https://b61d9a0c-54d1-47a6-971e-9b24c5dea7b4.selstorage.ru/thebigboy.mp4

[12] объектное хранилище Selectel: https://selectel.ru/services/cloud/storage/?utm_source=habr.com&utm_medium=referral&utm_campaign=storage_article_multiparts3_040325_content

[13] aws cli: https://docs.selectel.ru/cloud/object-storage/tools/aws-cli/

[14] rclone: https://docs.selectel.ru/cloud/object-storage/tools/rclone/

[15] s3cmd: https://docs.selectel.ru/cloud/object-storage/tools/s3cmd/

[16] cyberduck: https://docs.selectel.ru/cloud/object-storage/tools/cyberduck/

[17] s3fs: https://docs.selectel.ru/cloud/object-storage/tools/s3fs/

[18] мы стали официальными технологическими партнерами: https://rclone.org/s3/#selectel

[19] Источник: https://habr.com/ru/companies/selectel/articles/887698/?utm_source=habrahabr&utm_medium=rss&utm_campaign=887698