eagspoo eagspoo - 1 year ago 99
Node.js Question

s3.getSignedUrl ResponseContentDisposition parameter not working

I'm successfully generating a signed url that I can then use for a limited time to download resources from my s3 bucket. However I'm trying to use the ResponseContentDisposition attribute in the params as documented here:

  1. http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getSignedUrl-property

  2. http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getObject-property

I'm not sure if I'm doing this wrong but for some reason the headers are not being set. For example if I use the url I get back from s3.getSignedUrl:

curl -i "https://foo-dev.s3.amazonaws.com/images/foo.jpg?AWSAccessKeyId=AKIAICBHUC26S6B446PQ&Expires=1468359314&Signature=EeBqx1G83oeusarBl2KUbbCCBgA%3D&response-content-disposition=attachment%3B%20filename%3Ddata.jpg"

the headers are:

x-amz-id-2: SG9rjYQCcuqgKfjBmMbDQC2CNLcnqBAFzP7zINa99VYUwNijPOm5Ea/5fllZ6cnt/Qti7e26hbE=
x-amz-request-id: 2670068008525B1D
Date: Tue, 12 Jul 2016 21:26:16 GMT
Content-Disposition: inline; filename=foo.jpg
Last-Modified: Tue, 12 Jul 2016 00:47:23 GMT
ETag: "2a8e36651b24769170f4faa429f40f54"
Accept-Ranges: bytes
Content-Type: image/jpeg
Content-Length: 43373
Server: AmazonS3

I'm setting this, using the javascript s3 sdk like this:

function tempRedirect(req, res) {
var filename = req.params[0];
var contentDisposition = 'attachment; filename=data.jpg';
var params = {
Bucket: S3_BUCKET,
ResponseContentDisposition: contentDisposition,
Key: checkTrailingSlash(getFileKeyDir(req)) + filename
var s3 = new aws.S3(s3Options);
s3.getSignedUrl('getObject', params, function(err, url) {

The docs are pretty light and I can only find PHP examples but it does look like I'm setting content disposition correctly.

Anyone know what is going wrong here??

Answer Source

According to RFC- 2616, your value is malformed.

The expected format is attachment; filename="funny- cat.jpg". The filename is a quoted string.

And, my original assumption was that S3 was rejecting it as invalid and silently refusing to replace the value.

Subsequent tests reveal unexpected behavior: if Content-Disposition is not stored with the object, then &response-content-disposition=... works as expected, setting the response header. But if there is a header stored with the object, this query string parameter does not have the documented effect of "overriding" that value.

Conversely, &response-content-type=... does override a stored Content-Type: for the object.

That's what a few quick tests revealed for me.

But this appears to be a bug -- or more accurately, some kind of regression -- in S3. According to one support forum post, the behavior is actually inconsistent, sometimes working and sometimes not.

S3 is aware of this issue and we are working to resolve it. (2016-07-12)