web-dev-qa-db-ja.com

S3 Python-署名済みパーツURLを使用したs3へのマルチパートアップロード

署名済みのパートURLを使用してマルチパートアップロードを試みましたが失敗しました。

これは私が従う手順です(1-3はサーバー側にあり、4はクライアント側にあります):

  1. 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. マルチパートアップロードを開始します。
upload = s3.create_multipart_upload(
    Bucket=AWS_S3_BUCKET,
    Key=key,
    Expires=datetime.now() + timedelta(days=2),
)
upload_id = upload["UploadId"]
  1. パーツのアップロード用の事前署名付きURLを作成します。

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",
)

署名済みのURLをクライアントに返します。

  1. クライアントで、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",
    },
)

そして、アップロードしようとすると、次のいずれかが得られます:

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

または:

<?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>

アップロードがまだ存在し、それをリストすることはできますが。

誰かが私が間違っていることを教えてもらえますか?

12
Viktor Kerkez

代わりに pre-signed POST を試しましたか?ここにAWS Pythonそれのリファレンスがあります: https://docs.aws.Amazon.com/sdk-for-php/v3/developer-guide/s3-presigned- post.html

これにより、クライアントの観点からプロキシの制限が回避される可能性があります。

pre signed POST example

最後の手段として、古き良きREST APIをいつでも試すことができますが、問題はあなたのコードにもboto3にもないとは思いません: https:// docs。 aws.Amazon.com/AmazonS3/latest/dev/UsingRESTAPImpUpload.html

0
Fabio Manzano