带有元数据的AWS S3预签名URL

问题描述 投票:0回答:5

我正在尝试使用下面的 boto3 创建预签名 URL

s3 = boto3.client(
    's3', 
    aws_access_key_id=settings.AWS_ACCESS_KEY, 
    aws_secret_access_key=settings.AWS_ACCESS_SECRET, 
    region_name=settings.AWS_SES_REGION_NAME,
    config=Config(signature_version='s3v4')
)
metadata = {
    'test':'testing'
}
presigned_url = s3.generate_presigned_url(
ClientMethod='put_object', 
Params={
    'Bucket': settings.AWS_S3_BUCKET_NAME,
    'Key': str(new_file.uuid),
    'ContentDisposition': 'inline',
    'Metadata': metadata
})

因此,在生成 URL 并尝试使用 Ajax 将其上传到 S3 后,它给出了 403 禁止。如果我在创建 URL 时删除 Metadata 和 ContentDisposition,它就会成功上传。

Boto3版本:1.9.33

下面是我参考的文档: https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Client.generate_presigned_url

django python-2.7 boto3
5个回答
15
投票

是的,我成功了, 基本上,在生成签名 URL 后,我需要将标头中的所有元数据和 Content-Dispostion 与签名 URL 一起发送。 例如:我的元数据字典是 {'test':'test'} 那么我需要在标头中发送此元数据,即 x-amz-meta-test 及其值和 content-dispostion 到 AWS


5
投票

我发现元数据对象需要是键/值对,值作为字符串(示例是 Nodejs lambda):

const AWS = require('aws-sdk');
const s3 = new AWS.S3();

exports.handler = async (event) => {
    const { key, type, metadata } = JSON.parse(event.body);

    // example
    /*metadata: {
      foo: 'bar',
      x: '123',
      y: '22.4213213'
    }*/

    return await s3.getSignedUrlPromise('putObject', {
        Bucket: 'the-product-uploads',
        Key: key,
        Expires: 300,
        ContentType: type,
        Metadata: metadata
    });
};

然后在请求标头中,您需要显式添加每个 k/v:

await fetch(signedUrl, {
      method: "PUT",
      headers: {
        "Content-Type": fileData.type,
        "x-amz-meta-foo": "bar",
        "x-amz-meta-x": x.toString(),
        "x-amz-meta-y": y.toString()
      },
      body: fileBuffer
    });

4
投票

我正在使用

createPresignedPost
,对我来说,我通过将我想要的元数据添加到
Fields
参数来实现此功能,如下所示:-

const params = {
    Expires: 60,
    Bucket: process.env.fileStorageName,
    Conditions: [['content-length-range', 1, 1000000000]], // 1GB
    Fields: {
        'Content-Type': 'application/pdf',
        key: strippedName,
        'x-amz-meta-pdf-type': pdfType,
        'x-amz-meta-pdf-id': pdfId,
    },
};

只要您将文件元数据中所需的数据传递给用于创建

preSignedPost
响应的 lambda,那么上述操作就会起作用。希望能帮助别人...


2
投票

在 boto 中,您应该提供

Metadata
参数来传递键、值元数据的字典。您不需要将密钥命名为
x-amz-meta
,因为显然 boto 现在正在为您做这件事。

此外,上传到预签名 URL 时我不必再次传递元数据:

params = {'Bucket': bucket_name, 
          'Key': object_key, 
          'Metadata': {'test-key': value}
         }

response = s3_client.generate_presigned_url('put_object',
                                             Params=params,
                                             ExpiresIn=3600)

我在 API 后面的 lambda 函数中使用类似的代码


0
投票

向小组提出的问题 - 有人有可以包含在参数中的元数据示例吗?

我收到错误

botocore.exceptions.ParamValidationError:参数验证失败: 输入中的未知参数:“元数据”,必须是以下之一:Bucket、IfMatch、IfModifiedSince、IfNoneMatch、IfUnmodifiedSince、Key、Range、ResponseCacheControl、ResponseContentDisposition、ResponseContentEncoding、ResponseContentLanguage、ResponseContentType、ResponseExpires、VersionId、SSECustomerAlgorithm、SSECustomerKey、SSECustomerKeyMD5、RequestPayer、零件编号、预期桶所有者、校验和模式

© www.soinside.com 2019 - 2024. All rights reserved.