s3.getSignedUrl的ResponseContentDisposition参数无法正常工作

9
我成功地生成了一个签名 URL,可以在有限的时间内使用它来从我的 S3 存储桶下载资源。然而,我正在尝试使用 params 中的 ResponseContentDisposition 属性,如此文档所述:
  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
我不确定是否做错了什么,但出于某种原因,标题未被设置。例如,如果我使用从s3.getSignedUrl获得的url:
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"
标题是:
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

我正在使用 JavaScript S3 SDK 进行设置,代码如下:

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) {
        res.redirect(url);
    });
};

文档非常简洁,我只能找到PHP示例,但看起来我已经正确设置了内容的分发。有人知道这里出了什么问题吗?

在使用ResponseContentDisposition之前,您不应该需要它。确保在最初将文件放入S3存储桶时,向putObject方法传递一个内容类型参数(例如,可能是contentType:'image/jpeg')。然后,当您通过预签名URL下载它们时,对象已经包含处理它作为JPG附件所需的必要元数据;这意味着当您尝试通过预签名URL下载对象时,它知道自动打开一个文件选择器,询问您想要保存适当类型的附件的位置。 - Allison
1个回答

11
根据RFC-2616,您的值格式不正确。
预期格式为attachment; filename="funny-cat.jpg"。文件名是带引号的字符串。
而我的最初假设是S3将其拒绝为无效值,并默默地拒绝替换该值。
随后的测试显示出意外的行为:如果对象未存储Content-Disposition,则&response-content-disposition=...按预期工作,设置响应头。但是,如果对象中存储了头,则此查询字符串参数没有"覆盖"该值的文档化效果。
相反,&response-content-type=...确实可以覆盖对象的已存储Content-Type:
这是我进行了几个快速测试后发现的情况。
但这似乎是S3中的一个错误--或更准确地说,是某种退化。根据一个支持论坛帖子,该行为实际上是不一致的,有时起作用,有时不起作用。
S3已经意识到这个问题,我们正在努力解决。(2016-07-12) https://forums.aws.amazon.com/thread.jspa?threadID=235006

我已经尝试过带引号和不带引号的方式。但是S3始终使用原始Content-disposition并忽略我的ReponseContentDisposition参数。我是不是完全错误地调用了它?或者可能我误解了这个参数应该如何改变实际下载中的头部? - eagspoo
实际上,我应该能够将contentDisposition设置为“foo bar bar”,尽管这完全是错误的,但我期望S3只是将该值反映回给我。如果他们对我的设置进行了一些验证并因其格式不正确而忽略它,则getObject和getSignedUrl不会以任何方式让我知道,并且可能应该直接失败。 - eagspoo
同意,静默失败是出乎意料的,但这是我能想到的唯一可能性,因为你正在尝试做的应该正是你想要的。它允许你在下载时设置响应头,覆盖存储在对象中的头。 - Michael - sqlbot
啊,找到了。请查看更新后的答案。另外,你说得对,它没有经过验证。 - Michael - sqlbot
迈克尔,谢谢!看起来我们只需要等待! - eagspoo
我发现,如果你通过Web控制台生成重新签名的URL,响应中不会包含正确的Content-Disposition头部信息,但是如果你使用CLI或者SDK,它会包含。 - David Fevre

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接