【问题标题】:Unable to send/receive custom metadata on Amazon S3 Upload (using ng-file-upload)无法在 Amazon S3 Upload 上发送/接收自定义元数据(使用 ng-file-upload)
【发布时间】:2017-01-22 05:10:52
【问题描述】:

我正在使用 ng-file-upload 将 JPG 文件上传到我的 S3 存储桶。

file.upload = Upload.upload({
    url: "https://<my-bucket-name>.s3.amazonaws.com/", 
    method: "POST",
    data: {
        key: "custom-filename.jpg", 
        AWSAccessKeyId: "<AWSAccessKeyId>",
        acl: "public-read", 
        policy: <policy>, 
        signature: <signature>, 
        "Content-Type": "image/jpeg", 
        filename: file.name, 
        file: file, 
        Metadata: {
            "x-amz-meta-hello": "Custom Metadata Value"
        }
    }
});

我也尝试了以下(在上面的代码中)

Metadata: {
    hello: "Custom Metadata Value"
}

&简单

"x-amz-meta-hello": "Custom Metadata Value"

我已将自定义元数据包含在我的策略文件中

["starts-with", "x-amz-meta-hello", ""]

另外,S3 上 Bucket Permissions 下的 CORS 配置是

<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <AllowedMethod>HEAD</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <ExposeHeader>x-amz-meta-hello</ExposeHeader>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>

以上代码和设置正常,JPG文件上传成功,但不知何故自定义元数据值没有设置。

成功上传后,我正在调用 Lambda 函数来调整 JPG 的大小并将其存储在单独的存储桶中。即使这部分工作正常,但我无法在我的 Lambda 函数中读取自定义元数据 (x-amz-meta-hello) 值。我需要该值来为上传的文件分配一个单独的文件夹。

在我的 Lambda 函数中读取自定义元数据

var s3 = new AWS.S3();
s3.headObject({
    Bucket: <BucketName>,
    Key: <S3ObjectKey>
}, function(err, data) {
    if (err) {
        console.log(err);
    }
    else
    {   
        console.log(data);
    }     
});

不确定我在这里遗漏了什么......请告知。

谢谢。 (AngularJS 版本 1.5.0,ng-file-upload 版本 12.2.9,Google Chrome 版本 53.0.2785.113 on OSX 10.10.5)

【问题讨论】:

  • 严格按照直觉:消除Metadata: {}构造,并将元数据键放在文件信息上方:... "Content-Type": "image/jpeg", "x-amz-meta-hello": "Custom Metadata Value", filename: file.name, ...
  • 谢谢...完美运行...

标签: amazon-s3 ng-file-upload


【解决方案1】:

删除Metadata: { ... } 构造,因为您正在构建一个具有扁平键空间的HTML 表单。在其他地方,您可能会看到经过特殊处理的元数据,其中Metadata: { "hello": "world" } 之类的东西神奇地变成了x-amz-meta-hello: world,但在这里不适用。相反,元数据需要start with x-amz-meta-,而且由于我们是making a POST request,它是在表单数据中提供的,而不是作为标题提供。

因为文件数据需要是最后一个表单元素,所以将元数据键放在文件信息上方,例如:

...
"Content-Type": "image/jpeg", 
"x-amz-meta-hello": "Custom Metadata Value", 
filename: file.name, 
...

您的 policy condition 必须使用 $ 引用元数据名称才能工作 (["starts-with", "$x-amz-meta-hello", ""])。请注意,要接受该字段,必须有策略,但此特定条件不会限制该字段包含特定值。

另请注意,&lt;ExposeHeader&gt;x-amz-meta-hello&lt;/ExposeHeader&gt; 不是允许上传所必需的。 &lt;ExposeHeader&gt; 允许浏览器将该响应标头返回给 AJAX 请求的调用代码。未列出的标头(“简单”标准标头除外,例如Content-Type)否则对调用代码隐藏。 CORS 最初是违反直觉的,直到您了解它基于 Web 浏览器本身被假定为善意但幼稚的想法。 CORS 允许浏览器执行其他情况下不会执行的操作,例如将特定标头返回给调用者。

【讨论】:

  • 这似乎不对,如果您尝试将元数据添加到表单数据对象,您会收到一个错误响应,抱怨额外的字段。同样根据我从 S3 文档中了解到的情况,元数据应该通过以 x-amz-meta- 开头的标头提供。 (这允许文件上传,但元数据未设置。)
  • 没关系,我弄错了。对于 POST 请求,标头应该作为表单数据发送。 docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html我为过早的否决表示歉意。
  • 此外,策略条件需要使用$x-amz-meta-hello 才能工作。
  • @RahatAhmed 谢谢,您的编辑已获得批准,因此您可以在方便时取消投票。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-30
  • 2019-02-04
  • 1970-01-01
  • 1970-01-01
  • 2015-11-28
  • 2012-10-23
相关资源
最近更新 更多