执行POST请求时,不会设置Amazon S3内容类型

use*_*811 5 php http amazon-s3 amazon-web-services

AccessDenied Invalid according to Policy: Extra input fields: content-type

当我有这个

------WebKitFormBoundaryZIsnhgiAKpAVIsBT
Content-Disposition: form-data; name="acl"

public-read
------WebKitFormBoundaryZIsnhgiAKpAVIsBT
Content-Disposition: form-data; name="awsaccesskeyid"

my-access-key-id
------WebKitFormBoundaryZIsnhgiAKpAVIsBT
Content-Disposition: form-data; name="bucket"

my-bucket
------WebKitFormBoundaryZIsnhgiAKpAVIsBT
Content-Disposition: form-data; name="Content-Type"

image/png
------WebKitFormBoundaryZIsnhgiAKpAVIsBT
Content-Disposition: form-data; name="key"

images/anime_girl.png
------WebKitFormBoundaryZIsnhgiAKpAVIsBT
Content-Disposition: form-data; name="policy"

my-policy
------WebKitFormBoundaryZIsnhgiAKpAVIsBT
Content-Disposition: form-data; name="signature"

my-signature
------WebKitFormBoundaryZIsnhgiAKpAVIsBT
Content-Disposition: form-data; name="success_action_status"

201
------WebKitFormBoundaryZIsnhgiAKpAVIsBT
Content-Disposition: form-data; name="file"; filename="anime_girl.png"
Content-Type: image/png
Run Code Online (Sandbox Code Playgroud)

但是,如果我Content Type在下面的代码中完全省略了该文件,则会上传该文件但没有正确的内容类型.

        "acl" => "public-read",
        "awsaccesskeyid" => $s3->getAwsAccessKeyId(),
        "bucket" => $s3->getBucket(),
        "Content-Type" => $inputs['type'],
        "key" => "images/" . $inputs['name'],
        "policy" => $s3->getPolicy(true),
        "signature" => $s3->getSignedPolicy(),
        "success_action_status" => "201"
Run Code Online (Sandbox Code Playgroud)

我也尝试过添加内容类型policy,我收到了这个错误

AccessDenied Invalid according to Policy: Policy Condition failed: ["starts-with", "Content-Type", "image/png"]

我尝试了其他一些建议并得到了这个错误

AccessDenied Invalid according to Policy: Policy Condition failed: ["eq", "Content-Type", "image/png"]

这是我的角色配置

<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <AllowedMethod>DELETE</AllowedMethod>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>
Run Code Online (Sandbox Code Playgroud)

那么如何以其他方式指定内容类型或修复此问题呢?

编辑

当我省略任何类型的内容类型(我没有在后端指定任何内容)时,我得到了像Ben这样的请求有效载荷

------WebKitFormBoundaryUjxIo0gCBYg7AqJt
Content-Disposition: form-data; name="acl"

public-read
------WebKitFormBoundaryUjxIo0gCBYg7AqJt
Content-Disposition: form-data; name="awsaccesskeyid"

xxxx
------WebKitFormBoundaryUjxIo0gCBYg7AqJt
Content-Disposition: form-data; name="bucket"

xxxxx
------WebKitFormBoundaryUjxIo0gCBYg7AqJt
Content-Disposition: form-data; name="key"

images/Elf-Anime-Warrior-Wallpaper.jpg
------WebKitFormBoundaryUjxIo0gCBYg7AqJt
Content-Disposition: form-data; name="policy"

xxxx
------WebKitFormBoundaryUjxIo0gCBYg7AqJt
Content-Disposition: form-data; name="signature"

0BbpI0AP0wL3S1cBfo9n9tOp+N8=
------WebKitFormBoundaryUjxIo0gCBYg7AqJt
Content-Disposition: form-data; name="success_action_status"

201
------WebKitFormBoundaryUjxIo0gCBYg7AqJt
Content-Disposition: form-data; name="file"; filename="Elf-Anime-Warrior-Wallpaper.jpg"
Content-Type: image/jpeg


------WebKitFormBoundaryUjxIo0gCBYg7AqJt--
Run Code Online (Sandbox Code Playgroud)

问题是,在存储桶中,文件的内容类型为binary/octet-stream,因此图像不会在浏览器中查看,而是下载(这不是我想要的).因此,当我的请求有效负载如上所述时,我不确定为什么亚马逊没有正确设置内容类型.

13k*_*13k 7

根据Amazon S3文档,您确实可以将其Content-Type作为表单字段传递,但您需要在策略中允许这样做.

所以你需要这样的东西:

政策:

{
  "expiration": "2007-12-01T12:00:00.000Z",
  "conditions": [
    {"acl": "public-read" },
    {"bucket": "johnsmith" },
    ["starts-with", "$key", "user/eric/"],
    ["starts-with", "$Content-Type", ""],
    ...
  ]
}
Run Code Online (Sandbox Code Playgroud)

这里的相关行是["starts-with", "$Content-Type", ""].文档指出类型"匹配任何"的条件应该是带有空值的"starts-with".如果要将内容类型限制为某种内容,则应使用["starts-with", "$Content-Type", "image/"],例如.

形成:

(从S3文档中获取的示例,相应地更改值).

<form action="http://examplebucket.s3.amazonaws.com/" method="post" enctype="multipart/form-data">
  <input type="hidden" name="key" value="user/user1/${filename}">
  <input type="hidden" name="acl" value="public-read">
  <input type="hidden" name="success_action_redirect" value="http://examplebucket.s3.amazonaws.com/successful_upload.html">
  <input type="hidden" name="Content-Type" value="binary/octet-stream">
  <input type="hidden" name="Policy" value='<Base64-encoded policy string>'>
  <input type="hidden" name="x-amz-meta-uuid" value="14365123651274">
  <input type="hidden" name="X-Amz-Signature" value="<signature-value>">
  <input type="hidden" name="X-Amz-Credential" value="AKIAIOSFODNN7EXAMPLE/20130806/us-east-1/s3/aws4_request">
  <input type="hidden" name="X-Amz-Algorithm" value="AWS4-HMAC-SHA256">
  <input type="hidden" name="X-Amz-Date" value="20130806T000000Z">

  Tags for File: 
  <input type="input" name="x-amz-meta-tag" value=""><br>
  File: 
  <input type="file" name="file"><br>

  <input type="submit" name="submit" value="Upload to Amazon S3">
</form>
Run Code Online (Sandbox Code Playgroud)

正如您在第一个有效负载中所做的那样,您确实为表单设置了"Content-Type"字段.这与更新的政策一起应该有效.

但请注意,如果您事先知道要上载的文件的类型,则应将策略和表单字段都设置为该类型.但是如果你要上传不同类型的文件,你可以在策略中将Content-Type条件设置为"匹配任意",你可以编写一个简单的javascript拦截submit表单事件来动态更改Content-Type字段(这里是借助于jQuery的):

$("#s3-form").on("submit", function() {
  var contentTypeField = $("input[name='Content-Type']", this),
      fileField = $("input[type='file']", this),
      selectedFiles = fileField.get(0).files;

  if (files.length > 0) {
    // we're uploading a single file, so get the type for the first selected file
    contentTypeField.val(selectedFiles[0].type);
  }
});
Run Code Online (Sandbox Code Playgroud)


Scu*_*zzy -1

尝试ContentType在“婴儿车”级别数组内进行偏移。

"acl" => "public-read",
"awsaccesskeyid" => $s3->getAwsAccessKeyId(),
"bucket" => $s3->getBucket(),
"key" => "images/" . $inputs['name'],
"policy" => $s3->getPolicy(true),
"signature" => $s3->getSignedPolicy(),
"success_action_status" => "201",
// indent "ContentType" within a "params" array
"params" => array(
    "ContentType" => $inputs['type']
)
Run Code Online (Sandbox Code Playgroud)