簡體   English   中英

python AWS boto3 創建預簽名 url 用於文件上傳

[英]python AWS boto3 create presigned url for file upload

我正在為客戶端將視頻文件上傳到 s3 的應用程序編寫 django 后端。 我想使用預簽名的 url,因此 django 服務器將簽署 url 並將其傳遞回客戶端,然后客戶端將其視頻上傳到 s3。 問題是, generate_presigned_url 方法似乎不知道 s3 客戶端 upload_file 方法......

按照此示例,我使用以下代碼生成 url 用於上傳:

s3_client = boto3.client('s3')
try:
    s3_object_name = str(uuid4()) + file_extension
    params = {
        "file_name": local_filename,
        "bucket": settings.VIDEO_UPLOAD_BUCKET_NAME,
        "object_name": s3_object_name,
    }
    response = s3_client.generate_presigned_url(ClientMethod="upload_file",
                                                Params=params,
                                                ExpiresIn=500)
except ClientError as e:
    logging.error(e)
    return HttpResponse(503, reason="Could not retrieve upload url.")

運行它時出現錯誤:

文件“/Users/bridgedudley/.local/share/virtualenvs/ShoMe/lib/python3.6/site-packages/botocore/signers.py”,第 574 行,在 generate_presigned_url operation_name = self._PY_TO_OP_NAME[client_method] KeyError: 'upload_file '

觸發異常:

botocore.exceptions.UnknownClientMethodError:客戶端沒有方法:upload_file

調試后,我發現 self._PY_TO_OP_NAME 字典僅包含此處提供的 s3 客戶端命令的子集: 在此處輸入圖像描述

向下滾動到“上傳”... 在此處輸入圖像描述

沒有 upload_file 方法,我使用“list_buckets”嘗試了相同的代碼,並且效果很好。 給我一個預簽名的 url,其中列出了簽名者憑據下的存儲桶。

因此,如果沒有 generate_presigned_url function 中可用的 upload_file 方法,我該如何實現我想要的功能?

謝謝!

除了已經提到的用法之外:

boto3.client('s3').generate_presigned_url('put_object', Params={'Bucket':'your-bucket-name', 'Key':'your-object-name'})

您還可以使用:

boto3.client('s3').generate_presigned_post('your-bucket_name', 'your-object_name')

參考: https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3-presigned-urls.html#generating-a-presigned-url-to-upload-a-file

URL的樣品生成:

import boto3

bucket_name = 'my-bucket'
key_name = 'any-name.txt'

s3_client = boto3.client('s3')
upload_details = s3_client.generate_presigned_post(bucket_name, key_name)

print(upload_details)

Output:

{'url': 'https://my-bucket.s3.amazonaws.com/', 'fields': {'key': 'any-name.txt', 'AWSAccessKeyId': 'QWERTYUOP123', 'x-amz-security-token': 'a1s2d3f4g5h6j7k8l9', 'policy': 'z0x9c8v7b6n5m4', 'signature': 'qaz123wsx456edc'}}

文件上傳示例:

import requests

filename_to_upload = './some-file.txt'

with open(filename_to_upload, 'rb') as file_to_upload:
    files = {'file': (filename_to_upload, file_to_upload)}
    upload_response = requests.post(upload_details['url'], data=upload_details['fields'], files=files)

print(f"Upload response: {upload_response.status_code}")

Output:

Upload response: 204

補充說明:

如文件所述:

預簽名的 URL 使用的憑證是生成 URL 的 AWS 用戶的憑證。

因此,確保將執行這一代預簽名 URL 的實體允許策略s3:PutObject能夠使用已簽名的 URL 將文件上傳到 S3。 創建后,可以通過不同的方式對其進行配置。 他們之中有一些是:

作為 Lambda function 的允許策略

或通過boto3:

s3_client = boto3.client('s3',
        aws_access_key_id="your-access-key-id",
        aws_secret_access_key="your-secret-access-key",
        aws_session_token="your-session-token",  # Only for credentials that has it
    )

或者關於工作環境:

# Run in the Linux environment
export AWS_ACCESS_KEY_ID="your-access-key-id"
export AWS_SECRET_ACCESS_KEY="your-secret-access-key"
export AWS_SESSION_TOKEN="your-session-token",  # Only for credentials that has it

或通過庫,例如 Django 的 django-storages

您應該可以在此處使用put_object方法。 它是一個純客戶端 object,而不是像upload_file這樣的元客戶端 object。 這就是upload_file沒有出現在client._PY_TO_OP_NAME中的原因。 這兩個函數確實采用不同的輸入,這可能需要對您的代碼進行輕微的重構。

put_object: https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Client.put_object

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM