添加 Content-Encoding header 到已签名的 URL 上传文件
Adding Content-Encoding header to signed URL uploaded files
我需要通过签名 URL.
将 Gziped 内容上传到 S3
以下是我如何使用 JS 后端生成已签名的 URL:
s3.createPresignedPost({
Bucket: 'name',
Fields: {
key: 'key'
}
})
我尝试将 Content-Encoding
header 传递给已签名的 URL POST 请求,但没有成功。 headers 在 s3 object.
上的设置不正确
我还尝试设置 post 上传 lambda 来更新元数据。它因错误 File is identical
错误
而失败
最后我尝试使用 cloudfront + lambda 来强制 header。这也失败了,错误指出 Content-Enconding
是一个受保护的错误。
--更新开始--
对于通过Ajax或JS脚本上传到S3,我建议使用s3.getSignedUrl
方法。 s3.createPresignedPost
仅适用于直接浏览器上传。
下面是我使用 this 指南创建的 Ajax jQuery 上传示例。
s3.getSignedUrl('putObject', {
Bucket: 'bucketName',
Key: 'sample.jpg.gz',
// This must match with your ajax contentType parameter
ContentType: 'binary/octet-stream'
/* then add all the rest of your parameters to AWS puttObect here */
}, function (err, url) {
console.log('The URL is', url);
});
Ajax PUT 脚本 - 从上面的函数调用中获取 Url 并在下面使用它。
$.ajax({
type: 'PUT',
url: "https://s3.amazonaws.com/bucketName/sample.jpg.gz?AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE&Content-Type=binary%2Foctet-stream&Expires=1547056786&Signature=KyTXdr8so2C8WUmN0Owk%2FVLw6R0%3D",
//Even thought Content-Encoding header was not specified in signature, it uploads fine.
headers: {
'Content-Encoding': 'gzip'
},
// Content type must much with the parameter you signed your URL with
contentType: 'binary/octet-stream',
// this flag is important, if not set, it will try to send data as a form
processData: false,
// the actual file is sent raw
data: theFormFile
}).success(function () {
alert('File uploaded');
}).error(function () {
alert('File NOT uploaded');
console.log(arguments);
});
在 S3 object 中,您应该在元数据下看到 Content-Type、Content-Encoding。
重要提示
当您尝试通过浏览器上 运行 的 JS 脚本上传时,通常浏览器会倾向于在调用 PUT
方法之前先发送 OPTIONS
方法预检(或 CORS 检查)。 OPTIONS 会出现 403 Forbidden
错误,因为 S3 存储桶上的 CORS 不允许这样做。我解决的一种方法是使用以下 CORS configuration on bucket level. Reference
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>PUT</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
--更新结束--
你试过吗?我刚刚使用示例 html given in AWS documentation. Reference - https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-HTTPPOSTConstructPolicy.html
测试了政策
s3.createPresignedPost({
Bucket: 'name',
Conditions: [
{ "Content-Encoding": "gzip" }
],
Fields: {
key: 'key'
}
})
更新 -
这是我到目前为止的观察。
我们确实需要检查一下您的客户端正在执行上传操作。如果你想在 MetaData 上设置 Content-Encoding
,那么你的 Pre-Signed Url 应该设置 Content-Encoding 属性。如果 Signed Url 没有,但您的请求 header 有,那么它会给您 Extra input fields: content-encoding
.
我已经用 Content-Encoding 签署了一个 url 并上传了一个包含以下示例的压缩文件 html。
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<form action="http://bucket-name.s3.amazonaws.com" method="post" enctype="multipart/form-data">
Key to upload:
<input type="input" name="key" value="sample.jpg.gz" /><br />
Content-Encoding:
<input type="input" name="Content-Encoding" value="gzip" /><br />
<input type="text" name="X-Amz-Credential" value="AKIAIOSFODNN7EXAMPLE/20190108/us-east-1/s3/aws4_request" />
<input type="text" name="X-Amz-Algorithm" value="AWS4-HMAC-SHA256" />
<input type="text" name="X-Amz-Date" value="20190108T220828Z" />
Tags for File:
<input type="hidden" name="Policy" value='bigbase64String' />
<input type="hidden" name="X-Amz-Signature" value="xxxxxxxx" />
File:
<input type="file" name="file" /> <br />
<!-- The elements after this will be ignored -->
<input type="submit" name="submit" value="Upload to Amazon S3" />
</form>
</html>
如果我不发送 Content-Encoding
header 它会给出错误 Policy Condition failed: ["eq", "$Content-Encoding", "gzip"]
注 -
如果您在上传时使用 https
,请确保您在 S3 端点上有正确的证书,否则您将收到证书错误。
我需要通过签名 URL.
将 Gziped 内容上传到 S3以下是我如何使用 JS 后端生成已签名的 URL:
s3.createPresignedPost({
Bucket: 'name',
Fields: {
key: 'key'
}
})
我尝试将 Content-Encoding
header 传递给已签名的 URL POST 请求,但没有成功。 headers 在 s3 object.
我还尝试设置 post 上传 lambda 来更新元数据。它因错误 File is identical
错误
最后我尝试使用 cloudfront + lambda 来强制 header。这也失败了,错误指出 Content-Enconding
是一个受保护的错误。
--更新开始--
对于通过Ajax或JS脚本上传到S3,我建议使用s3.getSignedUrl
方法。 s3.createPresignedPost
仅适用于直接浏览器上传。
下面是我使用 this 指南创建的 Ajax jQuery 上传示例。
s3.getSignedUrl('putObject', {
Bucket: 'bucketName',
Key: 'sample.jpg.gz',
// This must match with your ajax contentType parameter
ContentType: 'binary/octet-stream'
/* then add all the rest of your parameters to AWS puttObect here */
}, function (err, url) {
console.log('The URL is', url);
});
Ajax PUT 脚本 - 从上面的函数调用中获取 Url 并在下面使用它。
$.ajax({
type: 'PUT',
url: "https://s3.amazonaws.com/bucketName/sample.jpg.gz?AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE&Content-Type=binary%2Foctet-stream&Expires=1547056786&Signature=KyTXdr8so2C8WUmN0Owk%2FVLw6R0%3D",
//Even thought Content-Encoding header was not specified in signature, it uploads fine.
headers: {
'Content-Encoding': 'gzip'
},
// Content type must much with the parameter you signed your URL with
contentType: 'binary/octet-stream',
// this flag is important, if not set, it will try to send data as a form
processData: false,
// the actual file is sent raw
data: theFormFile
}).success(function () {
alert('File uploaded');
}).error(function () {
alert('File NOT uploaded');
console.log(arguments);
});
在 S3 object 中,您应该在元数据下看到 Content-Type、Content-Encoding。
重要提示
当您尝试通过浏览器上 运行 的 JS 脚本上传时,通常浏览器会倾向于在调用 PUT
方法之前先发送 OPTIONS
方法预检(或 CORS 检查)。 OPTIONS 会出现 403 Forbidden
错误,因为 S3 存储桶上的 CORS 不允许这样做。我解决的一种方法是使用以下 CORS configuration on bucket level. Reference
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>PUT</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
--更新结束--
你试过吗?我刚刚使用示例 html given in AWS documentation. Reference - https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-HTTPPOSTConstructPolicy.html
测试了政策s3.createPresignedPost({
Bucket: 'name',
Conditions: [
{ "Content-Encoding": "gzip" }
],
Fields: {
key: 'key'
}
})
更新 - 这是我到目前为止的观察。
我们确实需要检查一下您的客户端正在执行上传操作。如果你想在 MetaData 上设置 Content-Encoding
,那么你的 Pre-Signed Url 应该设置 Content-Encoding 属性。如果 Signed Url 没有,但您的请求 header 有,那么它会给您 Extra input fields: content-encoding
.
我已经用 Content-Encoding 签署了一个 url 并上传了一个包含以下示例的压缩文件 html。
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<form action="http://bucket-name.s3.amazonaws.com" method="post" enctype="multipart/form-data">
Key to upload:
<input type="input" name="key" value="sample.jpg.gz" /><br />
Content-Encoding:
<input type="input" name="Content-Encoding" value="gzip" /><br />
<input type="text" name="X-Amz-Credential" value="AKIAIOSFODNN7EXAMPLE/20190108/us-east-1/s3/aws4_request" />
<input type="text" name="X-Amz-Algorithm" value="AWS4-HMAC-SHA256" />
<input type="text" name="X-Amz-Date" value="20190108T220828Z" />
Tags for File:
<input type="hidden" name="Policy" value='bigbase64String' />
<input type="hidden" name="X-Amz-Signature" value="xxxxxxxx" />
File:
<input type="file" name="file" /> <br />
<!-- The elements after this will be ignored -->
<input type="submit" name="submit" value="Upload to Amazon S3" />
</form>
</html>
如果我不发送 Content-Encoding
header 它会给出错误 Policy Condition failed: ["eq", "$Content-Encoding", "gzip"]
注 -
如果您在上传时使用 https
,请确保您在 S3 端点上有正确的证书,否则您将收到证书错误。