【问题标题】:python AWS boto3 create presigned url for file uploadpython AWS boto3为文件上传创建预签名url
【发布时间】:2020-08-12 18:16:21
【问题描述】:

我正在为客户端将视频文件上传到 s3 的应用程序编写 django 后端。我想使用预签名的 url,所以 django 服务器将签署一个 url 并将其传递回客户端,然后客户端将他们的视频上传到 s3。问题是,generate_presigned_url 方法似乎不知道s3 客户端upload_file 方法...

按照这个example,我使用下面的代码来生成上传的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:“上传文件”

触发异常:

botocore.exceptions.UnknownClientMethodError:客户端没有方法:upload_file

经过调试,我发现 self._PY_TO_OP_NAME 字典只包含here 提供的 s3 客户端命令的子集:

向下滚动到“上传”...

没有upload_file 方法!我使用“list_buckets”尝试了相同的代码,它运行良好,给了我一个预签名的 url,列出了签名者凭据下的存储桶。

那么如果没有 generate_presigned_url 函数中的 upload_file 方法,我该如何实现我想要的功能呢?

谢谢!

【问题讨论】:

    标签: python amazon-s3 file-upload boto3 pre-signed-url


    【解决方案1】:

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

    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)
    

    输出:

    {'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}")
    

    输出:

    Upload response: 204
    

    补充说明:

    据记载:

    预签名 URL 使用的凭证是 AWS 用户的凭证 谁生成了 URL。

    因此,请确保执行这一代预签名 URL 的实体允许策略 s3:PutObject 能够使用签名 URL 将文件上传到 S3。创建后,可以通过不同的方式对其进行配置。其中一些是:

    作为 Lambda 函数的允许策略

    或者通过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

    【讨论】:

      【解决方案2】:

      您应该可以在此处使用put_object 方法。它是一个纯客户端对象,而不是像upload_file 这样的元客户端对象。这就是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

      【讨论】:

      • 这是否需要客户端将二进制视频数据发送到django?这就是我试图避免使用预签名网址的原因。
      • 我不是 Django 用户/构建者,但上传事务应该是代理,就像 upload_file 一样。我看不出有任何理由如何或为什么会以不同的方式处理它。
      • g_sexton 是对的,查看stackoverflow.com/questions/46429551/… 示例
      猜你喜欢
      • 2019-11-06
      • 2019-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-23
      • 1970-01-01
      • 2019-01-11
      • 1970-01-01
      相关资源
      最近更新 更多