Reputation: 16092
I'm using the following php function to give temporary access to the public for a private file.
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}";
}
I wanted to add the content disposition header so I can change the filename to test.mp3
when a user tries to access this url which defaults the filename to 982jdjd2p3.mp3
$privateUrl = array('privateUrl' => get_s3_signed_url('testbucket', '982jdjd2p3.mp3', $my_aws_key, $my_aws_secret_key, 60));
I tried adding the following line of code to the function
$file_name = 'test.mp3';
$authentication_params.= "&Content-Disposition={$file_name}";
However when I click on the url
http://s3.amazonAWS.com/testbucket/982jdjd2p3.mp3?AWSAccessKeyId=***&Expires=***&Signature=***&Content-Disposition=test.mp3
The proposed filename is to be saved as 982jdjd2p3.mp3
How do I override the content disposition header for s3 GET requests using this function?
See Also
Amazon S3 Change file download name
EDIT
Here is the most recent attempt to rename the file with a get request using this function.
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}";
}
Upvotes: 6
Views: 9293
Reputation: 173522
The problem with your function is that the header values should be encoded in the final hyperlink, but not for signing. The following function corrects that:
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";
}
Upvotes: 12
Reputation: 8830
Format of your Content-Disposition is invalid, Specify disposition-type
.
Example:
Content-Disposition: attachment; filename=test.mp3;
Use response-content-disposition
in signature and params:
$disposition = "response-content-disposition=" . urlencode("attachment; filename={$filename}");
/* ... */
$string_to_sign .= "?{$disposition}";
/* ... */
$authentication_params.= "&{$disposition}";
Upvotes: 1