¿Cómo puedo copiar archivos de más de 5 GB en Amazon S3?


La documentación de la API REST de Amazon S3 dice que hay un límite de tamaño de 5 gb para cargar en una operación PUT. Los archivos más grandes que eso tienen que ser cargados usando multipart. Fino.

Sin embargo, lo que necesito en esencia es cambiar el nombre de los archivos que podrían ser más grandes que eso. Por lo que sé, no hay ninguna operación de cambio de nombre o movimiento, por lo tanto, tengo que copiar el archivo a la nueva ubicación y eliminar la antigua. ¿Cómo se hace exactamente eso con archivos de más de 5 gb? Tengo que hacer una carga de varias partes desde el cubo a sí mismo? En ese caso, ¿cómo funciona la división del archivo en partes?

Al leer la fuente de boto, no parece que haga algo como esto automáticamente para archivos de más de 5 gb. ¿Hay algún soporte incorporado que me haya perdido?

Author: Pedro Werneck, 2012-04-27

3 answers

Por lo que sé, no hay ninguna operación de cambio de nombre o movimiento, por lo tanto, tengo para copiar el archivo a la nueva ubicación y eliminar la antigua.

Eso es correcto, es bastante fácil de hacer para objetos / archivos de menos de 5 GB mediante una operación PUT Object - Copy, seguida de una operación DELETE Object (ambas soportadas en boto por supuesto, ver copy_key () y delete_key()):

Esta implementación de la operación PUT crea una copia de un objeto eso ya está almacenado en Amazon S3. Una operación de copia PUT es la misma como realizar un GET y luego un PUT. Agregar el encabezado de la solicitud, x-amz-copy-source, hace que la operación PUT copie el objeto fuente en el cubo de destino.

Sin embargo, eso no es posible para objetos / archivos de más de 5 GB:

Nota
[...] Se crea una copia de su objeto de hasta 5 GB de tamaño en un solo atómico operación usando esta API. Sin embargo, para copiar un objeto mayor que 5 GB, debe utilizar la API de carga multiparte . Conceptual información [...], vaya a Cargando objetos Usando Carga Multiparte [...] [énfasis mío]

Boto mientras tanto soporta esto también por medio del método copy_part_from_key () ; desafortunadamente el enfoque requerido no está documentado fuera de la respectiva solicitud de extracción #425 (permitir la copia de varias partes comandos) (Aún no he probado esto):

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()

Es posible que desee estudiar las muestras respectivas sobre cómo lograr esto en Java o.NET eventualmente, lo que podría proporcionar más información sobre el enfoque general, consulte Copiar objetos Utilizando la API de carga Multiparte.

¡Buena suerte!


Apéndice

Tenga en cuenta la siguiente peculiaridad con respecto a la copia en general, que se pasa por alto fácilmente:

Al copiar un objeto, puede conservar la mayoría de los metadatos (predeterminado) o especificar nuevos metadatos. Sin embargo, el ACL no se conserva y se establece en privado para el usuario que realiza la solicitud . Para anular el configuración predeterminada de ACL, use el encabezado x-amz-acl para especificar una nueva ACL al generar una solicitud de copia. Para obtener más información, consulte Amazon S3 ACLs. [énfasis mío]

 23
Author: Steffen Opel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-06 23:18:37

Lo anterior estaba muy cerca de funcionar, desafortunadamente debería haber terminado con mp.complete_upload() en lugar del error upload_complete()!

He agregado un script de copia multiparte boto s3 que funciona aquí, basado en el ejemplo de AWS Java y probado con archivos de más de 5 GiB:

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

 10
Author: joshuadfranklin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-30 05:14:44

Encontré este método para cargar archivos más grandes que 5gigs y lo modificé para trabajar con un procedimiento de copia Boto. aquí está el original: 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()
 0
Author: Matt Farguson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-24 18:27:24