【问题标题】:Unable to override content disposition header in s3无法覆盖 s3 中的内容处置标头
【发布时间】:2012-09-24 02:01:11
【问题描述】:

我正在使用以下 php 函数为私有文件提供临时访问权限。

function get_s3_signed_url($bucket, $resource, $AWS_S3_KEY, $AWS_s3_secret_key, $expire_seconds) {
    $expires = time()+$expire_seconds;
    // S3 Signed URL creation
    $string_to_sign = "GET\n\n\n{$expires}\n/".str_replace(".s3.amazonAWS.com","", $bucket)."/$resource";
    $signature = urlencode(base64_encode((hash_hmac("sha1", utf8_encode($string_to_sign), $AWS_s3_secret_key, TRUE))));

    $authentication_params = "AWSAccessKeyId=".$AWS_S3_KEY;
    $authentication_params.= "&Expires={$expires}";
    $authentication_params.= "&Signature={$signature}";

    return $link = "http://s3.amazonAWS.com/{$bucket}/{$resource}?{$authentication_params}";
}       

我想添加内容处置标头,以便在用户尝试访问此 URL 时将文件名更改为 test.mp3,该 URL 将文件名默认为 982jdjd2p3.mp3

$privateUrl = array('privateUrl' => get_s3_signed_url('testbucket', '982jdjd2p3.mp3', $my_aws_key, $my_aws_secret_key, 60));

我尝试在函数中添加以下代码行

$file_name = 'test.mp3';       
$authentication_params.= "&Content-Disposition={$file_name}";

但是当我点击网址时

http://s3.amazonAWS.com/testbucket/982jdjd2p3.mp3?AWSAccessKeyId=***&Expires=***&Signature=***&Content-Disposition=test.mp3

建议的文件名保存为982jdjd2p3.mp3

如何使用此函数覆盖 s3 GET 请求的内容处置标头?

另见

Amazon S3 Change file download name

编辑

这是最近使用此函数通过获取请求重命名文件的尝试。

function get_s3_signed_url($bucket, $resource, $AWS_S3_KEY, $AWS_s3_secret_key, $expire_seconds) {
    $expires = time()+$expire_seconds;
    // S3 Signed URL creation
    $filename='moot.mp3';
    $disposition = "response-content-disposition=" . urlencode("attachment; filename={$filename}");            

    $string_to_sign = "GET\n\n\n{$expires}\n/".str_replace(".s3.amazonAWS.com","", $bucket)."/$resource";
    $string_to_sign .= "?{$disposition}";
    $signature = urlencode(base64_encode((hash_hmac("sha1", utf8_encode($string_to_sign), $AWS_s3_secret_key, TRUE))));

    $authentication_params = "AWSAccessKeyId=".$AWS_S3_KEY;  
    $authentication_params.= "&Expires={$expires}";
    $authentication_params.= "&Signature={$signature}";
    $authentication_params.= "&{$disposition}";

    return $link = "http://s3.amazonAWS.com/{$bucket}/{$resource}?{$authentication_params}";
}       

【问题讨论】:

    标签: php amazon-s3 amazon-web-services


    【解决方案1】:

    您的函数的问题是标头值应该在最终超链接中编码,而不是用于签名。以下函数更正了这一点:

    function get_s3_signed_url($bucket, $resource, $AWS_S3_KEY, $AWS_s3_secret_key, $expire_seconds, $save_as)
    {
        $expires = time()+$expire_seconds;
        // S3 Signed URL creation
        $headers = array(
            'response-content-disposition' => 'attachment; filename=' . $save_as,
        );
        $resource = str_replace(array('%2F', '%2B'), array('/', '+'), rawurlencode($resource));
    
        $string_to_sign = "GET\n\n\n$expires\n/$bucket/$resource";
        $final_url = "http://s3.amazonaws.com/$bucket/$resource?";
    
        $append_char = '?';
        foreach ($headers as $header => $value) {
            $final_url .= $header . '=' . urlencode($value) . '&';
            $string_to_sign .= $append_char . $header . '=' . $value;
            $append_char = '&';
        }
    
        $signature = urlencode(base64_encode(hash_hmac('sha1', $string_to_sign, $AWS_s3_secret_key, true)));
    
        return $final_url . "AWSAccessKeyId=$AWS_S3_KEY&Expires=$expires&Signature=$signature";
    }
    

    【讨论】:

    • 谢谢杰克!但是,它只保存为标题,直到第一个空格。例如,如果$save_as='hello world'; 文件将保存为hello。有什么办法吗?
    • @user784637 在这种情况下,您需要考虑在其周围添加双引号,例如filename="hello world.txt"
    【解决方案2】:

    您的Content-Disposition 格式无效,请指定disposition-type

    示例: Content-Disposition: attachment; filename=test.mp3;

    在签名和参数中使用response-content-disposition

    $disposition = "response-content-disposition=" . urlencode("attachment; filename={$filename}");
    /* ... */
    $string_to_sign .= "?{$disposition}";
    /* ... */
    $authentication_params.= "&{$disposition}";
    

    【讨论】:

    • 我对在哪里进行更改感到困惑,我可以在上面的 php 脚本中进行更改吗?什么是合适的代码?
    • 不幸的是,当我尝试获得指向带有以下错误的 .xml 页面的链接时 我们计算的请求签名与您提供的签名不匹配。检查您的密钥和签名方法。
    • 可能你忘记在签名中添加content-disposition
    • 谢谢伯纳德 - 我回家后试试这个
    • 抱歉,bernard - 这个语法不正确,请查看我对我正在使用的当前函数的编辑
    猜你喜欢
    • 1970-01-01
    • 2020-04-28
    • 2017-04-27
    • 2010-10-30
    • 2017-09-20
    • 2012-11-07
    • 2016-08-23
    • 2021-08-25
    • 2012-09-06
    相关资源
    最近更新 更多