Подтвердить что ты не робот

Как копировать файлы размером более 5 ГБ в Amazon S3?

В документации по API REST Amazon S3 указано ограничение на размер 5gb для загрузки в PUT-операции. Файлы, которые больше, чем они должны быть загружены с помощью multipart. Хорошо.

Однако мне нужно в основном переименовать файлы, которые могут быть больше. Насколько я знаю, нет операции переименования или перемещения, поэтому мне нужно скопировать файл в новое место и удалить старый. Как именно это делается с файлами размером более 5 ГБ? Я должен сделать многостраничную загрузку из ведра в себя? В этом случае, как работает разделение файла по частям?

Из чтения источника boto кажется, что он не делает ничего подобного автоматически для файлов размером более 5 ГБ. Есть ли встроенная поддержка, которую я пропустил?

4b9b3361

Ответ 1

Насколько я знаю, нет операции переименования или перемещения, поэтому у меня есть скопировать файл в новое место и удалить старый.

Правильно, это довольно легко сделать для объектов/файлов размером менее 5 ГБ с помощью операции PUT Object - Copy, за которой следует DELETE Object (оба из них поддерживаются в boto, см. copy_key() и delete_key()):

Эта реализация операции PUT создает копию объекта который уже хранится в Amazon S3. Операция копирования PUT одинакова как выполнение GET, а затем PUT. Добавление заголовка запроса, x-amz-copy-source, делает операцию PUT копировать исходный объект в конечный ковш.

Однако это невозможно для объектов/файлов размером более 5 ГБ:

Примечание
[...] Вы создаете копию своего объекта размером до 5 ГБ в одном атомном используя этот API. Однако для копирования объекта, большего, чем 5 ГБ, вы должны использовать API многостраничной загрузки. Для концептуальных информация [...], перейдите к Загрузка объектов с помощью загрузки многостраничных файлов [...] [акцент мой]

Boto поддерживает это также с помощью метода copy_part_from_key(); к сожалению, требуемый подход не документируется вне соответствующего запроса pull # 425 (разрешить многокомпонентные команды копирования) (я еще не пробовал это сам)

import boto
s3 = boto.connect_s3('access', 'secret')
b = s3.get_bucket('destination_bucket')
mp = b.initiate_multipart_upload('tmp/large-copy-test.mp4')
mp.copy_part_from_key('source_bucket', 'path/to/source/key', 1, 0, 999999999)
mp.copy_part_from_key('source_bucket', 'path/to/source/key', 2, 1000000000, 1999999999)
mp.copy_part_from_key('source_bucket', 'path/to/source/key', 3, 2000000000, 2999999999)
mp.copy_part_from_key('source_bucket', 'path/to/source/key', 4, 3000000000, 3999999999)
mp.copy_part_from_key('source_bucket', 'path/to/source/key', 5, 4000000000, 4999999999)
mp.copy_part_from_key('source_bucket', 'path/to/source/key', 6, 5000000000, 5500345712)
mp.complete_upload()

Возможно, вам захочется изучить соответствующие образцы о том, как добиться этого в Java или .NET в конечном итоге, что может обеспечить более глубокое понимание общего подхода, см. Копирование объектов с помощью многостраничной загрузки API.

Удачи!


Приложение

Обратите внимание на следующую особенность копирования в целом, которую легко упустить:

При копировании объекта вы можете сохранить большинство метаданных (по умолчанию) или указать новые метаданные. Однако ACL не сохраняется и для пользователя, делающего запрос, назначается частным. Чтобы переопределить по умолчанию ACL, используйте заголовок x-amz-acl, чтобы указать новый ACL при генерации запроса на копирование. Для получения дополнительной информации см. Amazon S3 Списки управления доступом. [акцент мой]

Ответ 2

Выше было очень близко к работе, к сожалению, должно было закончиться mp.complete_upload() вместо опечатки upload_complete()!

Я добавил рабочую копию boto s3 multipart script здесь, на основе примера AWS Java и протестированный с файлами более 5 GiB:

https://gist.github.com/joshuadfranklin/5130355

Ответ 3

Я нашел этот метод для загрузки файлов размером более 5 гигабайт и изменения его для работы с процедурой копирования Boto. здесь оригинал: http://boto.cloudhackers.com/en/latest/s3_tut.html

import math
from boto.s3.connection import S3Connection
from boto.exception import S3ResponseError


conn = S3Connection(host=[your_host], aws_access_key_id=[your_access_key],
                    aws_secret_access_key=[your_secret_access_key])

from_bucket = conn.get_bucket('your_from_bucket_name')
key = from_bucket.lookup('my_key_name')
dest_bucket = conn.get_bucket('your_to_bucket_name')

total_bytes = key.size
bytes_per_chunk = 500000000

chunks_count = int(math.ceil(total_bytes/float(bytes_per_chunk)))
file_upload = dest_bucket.initiate_multipart_upload(key.name)
for i in range(chunks_count):
    offset = i * bytes_per_chunk
    remaining_bytes = total_bytes - offset
    print(str(remaining_bytes))
    next_byte_chunk = min([bytes_per_chunk, remaining_bytes])
    part_number = i + 1
    file_upload.copy_part_from_key(dest_bucket.name, key.name, part_number,
                                   offset, offset + next_byte_chunk - 1)
file_upload.complete_upload()