web-dev-qa-db-fra.com

S3 Python - Téléchargement en plusieurs parties vers s3 avec des URL de pièces prédéfinies

J'essaie en vain d'effectuer un téléchargement en plusieurs parties avec des URL de pièces pré-signées.

Voici la procédure que je suis en train de suivre (1-3 est côté serveur, 4 côté client):

  1. Instancier le client boto.
import boto3
from botocore.client import Config

s3 = boto3.client(
    "s3",
    region_name=aws.default_region,
    aws_access_key_id=aws.access_key_id,
    aws_secret_access_key=aws.secret_access_key,
    config=Config(signature_version="s3v4")
)
  1. Lancer le téléchargement en plusieurs parties.
upload = s3.create_multipart_upload(
    Bucket=AWS_S3_BUCKET,
    Key=key,
    Expires=datetime.now() + timedelta(days=2),
)
upload_id = upload["UploadId"]
  1. Créez une URL pré-signée pour le téléchargement de la pièce.

part = generate_part_object_from_client_submited_data(...)

part.presigned_url = s3.generate_presigned_url(
    ClientMethod="upload_part",
    Params={
        "Bucket": AWS_S3_BUCKET,
        "Key": upload_key,
        "UploadId": upload_id,
        "PartNumber": part.no,
        "ContentLength": part.size,
        "ContentMD5": part.md5,
    },
    ExpiresIn=3600,  # 1h
    HttpMethod="PUT",
)

Renvoyez l'URL pré-signée au client.

  1. Sur le client, essayez de télécharger la pièce à l'aide de requests.
part = receive_part_object_from_server(...)

with io.open(filename, "rb") as f:
    f.seek(part.offset)
    buffer = io.BytesIO(f.read(part.size))

r = requests.put(
    part.presigned_url,
    data=buffer,
    headers={
        "Content-Length": str(part.size),
        "Content-MD5": part.md5,
        "Host": "AWS_S3_BUCKET.s3.amazonaws.com",
    },
)

Et lorsque j'essaie de télécharger, je reçois:

urllib3.exceptions.ProtocolError:
('Connection aborted.', BrokenPipeError(32, 'Broken pipe'))

Ou:

<?xml version="1.0" encoding="UTF-8"?>
<Error>
  <Code>NoSuchUpload</Code>
  <Message>
    The specified upload does not exist. The upload ID may be invalid,
    or the upload may have been aborted or completed.
  </Message>
  <UploadId>CORRECT_UPLOAD_ID</UploadI>
  <RequestId>...</RequestId>
  <HostId>...</HostId>
</Error>

Même si le téléchargement existe toujours et que je peux le répertorier.

Quelqu'un peut-il me dire ce que je fais mal?

12
Viktor Kerkez

Avez-vous essayé POST pré-signé à la place? Voici la référence AWS Python: https://docs.aws.Amazon.com/sdk-for-php/v3/developer-guide/s3-presigned- post.html

Cela contournera potentiellement les limitations du proxy du point de vue du client, le cas échéant:

pre signed POST example

En dernier recours, vous pouvez toujours essayer la bonne vieille REST API, bien que je ne pense pas que le problème soit dans votre code et ni dans boto3: https: // docs. aws.Amazon.com/AmazonS3/latest/dev/UsingRESTAPImpUpload.html

0
Fabio Manzano